-
Notifications
You must be signed in to change notification settings - Fork 89
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
js[patch]: simple evaluator args #1264
Conversation
js/src/evaluation/evaluator.ts
Outdated
@@ -110,6 +110,21 @@ export class DynamicRunEvaluator<Func extends (...args: any[]) => any> | |||
langSmithRunAndExample: { run: Run; example: Example }; | |||
}) => { | |||
const { run, example } = input.langSmithRunAndExample; | |||
|
|||
// Check if the evaluator expects the new argument format | |||
const params = getEvaluatorParameters(evaluator); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the better/safer way to do this is to shim it with no source code inspection:
return evaluator({
...run,
run,
example,
inputs: example?.inputs,
outputs: run?.outputs,
referenceOutputs: example?.outputs,,
}, example);
Convention in JS is to ignore extra kwargs and args so it should work without breaking anyone.
Downside is it makes logging a little bit funkier but we can deprecate the old style(?) in the future
You could also maybe try this:
https://stackoverflow.com/questions/4848149/get-a-functions-arity
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CC @nfcampos I think I heard you should try to avoid Function.toString()
but I'm not actually sure why (other than the fact that the regexes for some of the below checks should be tweaked)
Perf probably isn't super important given this will only run once
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Googling around and tinkering in my terminal - implementation seems unclear, I think it may have some funny edge cases (at the very least arrow functions would definitely need a separate regex, along with async
, maybe others I'm not thinking about)
Would prefer to do something like the shim above in order to avoid any potential gotchas
js/src/evaluation/evaluator.ts
Outdated
@@ -110,6 +110,21 @@ export class DynamicRunEvaluator<Func extends (...args: any[]) => any> | |||
langSmithRunAndExample: { run: Run; example: Example }; | |||
}) => { | |||
const { run, example } = input.langSmithRunAndExample; | |||
|
|||
// Check if the evaluator expects the new argument format | |||
const params = getEvaluatorParameters(evaluator); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Googling around and tinkering in my terminal - implementation seems unclear, I think it may have some funny edge cases (at the very least arrow functions would definitely need a separate regex, along with async
, maybe others I'm not thinking about)
Would prefer to do something like the shim above in order to avoid any potential gotchas
js/src/evaluation/evaluator.ts
Outdated
const funcStr = func.toString(); | ||
|
||
// Check if the function accepts a single object parameter | ||
if (funcStr.match(/^\s*(?:async\s+)?(?:function\s*)?\(?\s*{\s*[a-zA-Z_]/)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would also need to account for at the very least arrow-declared functions () => {}
and async () => {}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should probably also update the types for RunEvaluatorLike
above right?
const outputs = runs.map((run) => run.outputs || {}); | ||
const referenceOutputs = examples.map((ex) => ex.outputs || {}); | ||
|
||
return Promise.resolve( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't need the Promise.resolve
, more standard to just make the outside function async
:
const wrapperSuperInner = traceable(
async (
_runs_: string,
_examples_: string
): Promise<EvaluationResult | EvaluationResults> => {
|
||
return evaluator( | ||
{ | ||
...run, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we just do the arity check for both of these?
Is there a world where there are some crazies out there declaring evaluators like this:
async (run) => {
}
I would prefer the shim in both places unless we want to drop support for the two arg syntax in the long run, in which case we should deprecate the other signature:
export type RunEvaluatorLike =
/** @deprecated NOTE */
| ((
run: Run,
example?: Example
) => Promise<EvaluationResult | EvaluationResults>)
/** @deprecated NOTE */
| ((run: Run, example?: Example) => EvaluationResult | EvaluationResults)
| ((args: {
run?: Run;
example?: Example;
inputs?: Record<string, any>;
outputs?: Record<string, any>;
referenceOutputs?: Record<string, any>;
}) => EvaluationResult | EvaluationResults)
| ((args: {
run?: Run;
example?: Example;
inputs?: Record<string, any>;
outputs?: Record<string, any>;
referenceOutputs?: Record<string, any>;
}) => Promise<EvaluationResult | EvaluationResults>);
const result = | ||
evaluator.length === 1 | ||
? await (evaluator as _ComparativeEvaluator)({ | ||
runs: options.randomizeOrder ? shuffle(runs) : runs, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Worth supporting evaluator(runs)?
js equivalent of #1200