Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

core[patch]: Passing the input object to the Retry Attempt Handler. #5081

Merged
merged 8 commits into from
Apr 22, 2024

Conversation

mauriciocirelli
Copy link
Contributor

@mauriciocirelli mauriciocirelli commented Apr 12, 2024

Hi,

This is related to the following discussion: How to capture and use the exception error on a Runnable With Retry Chain?.

Passing the input object to the retry attempt handler allows the developer to change it with the error information, making the chain capable of fixing the error in the next loop.

Retrying without fixing the error is very limited.. sometimes retrying the same calls would fix the issue, but usually, it doesnt.

Something like this would do the job:

RunnablePassthrough.assign({ 
  results: RunnableSequence.from([
	RunnablePassthrough.assign({ 
	  question: RunnableBranch.from([
		[
		  (input: any) => (input.error),
		  (input: any) => fix_errors(input.question, input.error),
		],
		(input: any) => input.question,
	  ]),
	}),
	RunnablePassthrough.assign({
	  // Clears the error
	  error: () => null,
	}),
	(input: any) => run_may_throw(input.question),
  ])
  .withRetry({
	onFailedAttempt: (error: any, input: any) => {
	  input.error = error.message;
	},
	stopAfterAttempt: 3,
  }),
})

The only thing that I would like to improve here is the async _batch<ReturnExceptions extends boolean = false>( inputs: RunInput[], configs?: RunnableConfig[], runManagers?: (CallbackManagerForChainRun | undefined)[], batchOptions?: RunnableBatchOptions) call (line 1375):

{
  onFailedAttempt: (error: any) => this.onFailedAttempt(error, inputs),
  retries: Math.max(this.maxAttemptNumber - 1, 0),
  randomize: true,
}

Is there a way to capture just the input that caused the exception? I am working around it passing the whole inputs array, but I think it would be nicer to just pass the faulty one.

I hope this interests the community.

Thank you.

@dosubot dosubot bot added the size:XS This PR changes 0-9 lines, ignoring generated files. label Apr 12, 2024
Copy link

vercel bot commented Apr 12, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
langchainjs-api-refs ✅ Ready (Inspect) Visit Preview 💬 Add feedback Apr 22, 2024 11:39pm
langchainjs-docs ✅ Ready (Inspect) Visit Preview Apr 22, 2024 11:39pm

@mauriciocirelli
Copy link
Contributor Author

Hi,

Any thoughts on this?

@mauriciocirelli
Copy link
Contributor Author

Hi, @jacoblee93

Any chance to have a look into this so we can get it merged?

Thank you!

@jacoblee93 jacoblee93 changed the title Passing the input object to the Retry Attempt Handler. core[patch]: Passing the input object to the Retry Attempt Handler. Apr 22, 2024
@jacoblee93
Copy link
Collaborator

Sorry for the delay! Looking now!

@dosubot dosubot bot added size:M This PR changes 30-99 lines, ignoring generated files. and removed size:XS This PR changes 0-9 lines, ignoring generated files. labels Apr 22, 2024
@jacoblee93
Copy link
Collaborator

Hey @mauriciocirelli, does it make sense to pass the entire input back for batch? Feels like it'd make more sense to just pass back the first failure?

@mauriciocirelli
Copy link
Contributor Author

mauriciocirelli commented Apr 22, 2024

Hey @mauriciocirelli, does it make sense to pass the entire input back for batch? Feels like it'd make more sense to just pass back the first failure?

Not at all.
That's where I got a bit lost on the code... I totally agree that we should pass just the input that caused the exception. It would also make the callback handler more standardized... But I could not find a way to do it. Would you mind pointing me how to get the input that caused the exception?

@jacoblee93
Copy link
Collaborator

What about just setting it on the thrown error:

          let firstException;
          for (let i = 0; i < results.length; i += 1) {
            const result = results[i];
            const resultMapIndex = remainingIndexes[i];
            // eslint-disable-next-line no-instanceof/no-instanceof
            if (result instanceof Error) {
              if (firstException === undefined) {
                firstException = result;
                (firstException as any).input = foo
              }
            }
            resultsMap[resultMapIndex.toString()] = result;
          }
          if (firstException) {
            throw firstException;
          }

@mauriciocirelli
Copy link
Contributor Author

mauriciocirelli commented Apr 22, 2024

What about just setting it on the thrown error:

          let firstException;
          for (let i = 0; i < results.length; i += 1) {
            const result = results[i];
            const resultMapIndex = remainingIndexes[i];
            // eslint-disable-next-line no-instanceof/no-instanceof
            if (result instanceof Error) {
              if (firstException === undefined) {
                firstException = result;
                (firstException as any).input = foo
              }
            }
            resultsMap[resultMapIndex.toString()] = result;
          }
          if (firstException) {
            throw firstException;
          }

Sounds good.

Have just pushed the changes.

@jacoblee93
Copy link
Collaborator

LGTM just fix test case

@mauriciocirelli
Copy link
Contributor Author

LGTM just fix test case

My bad. Looking into it.

@jacoblee93
Copy link
Collaborator

And run yarn format too please!

@mauriciocirelli
Copy link
Contributor Author

And run yarn format too please!

Yeah. I have seen that workflow failing too.
Just pushed.

@jacoblee93
Copy link
Collaborator

Thank you!

@mauriciocirelli
Copy link
Contributor Author

Thank you!

Im happy to contribute. Like this kind of PR, that helps making (mine and others) code cleaner.
Thank you for your time looking into it.

@jacoblee93
Copy link
Collaborator

Getting:

1371:36  error  Unexpected any. Specify a different type  @typescript-eslint/no-explicit-any

Can fix myself in a bit

@mauriciocirelli
Copy link
Contributor Author

mauriciocirelli commented Apr 22, 2024

Getting:

1371:36  error  Unexpected any. Specify a different type  @typescript-eslint/no-explicit-any

Can fix myself in a bit

I am waiting for everything to finish so I can push it... do not worry.

It is good for me to learn the workflows and how to fix them.

@jacoblee93
Copy link
Collaborator

Thank you!

@jacoblee93 jacoblee93 merged commit 8b78659 into langchain-ai:main Apr 22, 2024
23 checks passed
@mauriciocirelli mauriciocirelli deleted the runnable-retry-input branch April 22, 2024 23:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
auto:improvement Medium size change to existing code to handle new use-cases lgtm PRs that are ready to be merged as-is size:M This PR changes 30-99 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants