Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 90 additions & 9 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 13 additions & 1 deletion packages/workflowai/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,19 @@ const getCapitalInfo = workflowAI.agent<
id: 'get-capital-info',
schemaId: 1,
version: '1.4',
// Cache options:
// Cache options (can also be passed to the run function):
// - "auto" (default): if a previous run exists with the same version and input, and if
// the temperature is 0, the cached output is returned
// - "always": the cached output is returned when available, regardless
// of the temperature value
// - "never": the cache is never used
useCache: 'auto',
// Customize model fallback, (can also be passed to the run function):
// - defaults to 'auto' meaning that the model to fallback to is picked by WorkflowAI
// The selected model is in the same price range and depends on the error that was triggered
// - "never": the fallback is never used
// - list of model names: models to try in order after the primary model fails
useFallback: ['gpt-4o-mini', 'gpt-4o'],
});

// Run Your AI agent
Expand All @@ -69,6 +75,12 @@ async function getCapitalInfoRun() {
data: { duration_seconds, cost_usd, version },
} = await getCapitalInfo(input);

// Also possible to pass options to the run function:
// const { output } = await getCapitalInfo(input, {
// useCache: 'always',
// useFallback: 'never',
// });

console.log(output);
console.log('\nModel: ', version?.properties?.model);
console.log('Cost: $', cost_usd);
Expand Down
2 changes: 1 addition & 1 deletion packages/workflowai/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@workflowai/workflowai",
"version": "1.6.7",
"version": "1.6.8",
"type": "module",
"description": "WorkflowAI JS SDK",
"author": "WorkflowAI",
Expand Down
4 changes: 3 additions & 1 deletion packages/workflowai/src/WorkflowAI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ function optionsToRunRequest(
input: Record<string, never>,
options: Omit<RunOptions<true | false>, 'fetch'>
): RunRequest {
const { version, stream, metadata, useCache, privateFields } = options;
const { version, stream, metadata, useCache, privateFields, useFallback } =
options;

return {
task_input: input,
Expand All @@ -46,6 +47,7 @@ function optionsToRunRequest(
metadata,
use_cache: useCache || 'auto',
private_fields: privateFields,
use_fallback: useFallback,
};
}

Expand Down
5 changes: 5 additions & 0 deletions packages/workflowai/src/api/generated/openapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ export interface components {
* @description Fields marked as private will not be saved, none by default.
*/
private_fields?: ('task_input' | string)[] | null;
/**
* Use Fallback
* @description Whether to use fallback models if the primary model fails.
*/
use_fallback?: 'never' | 'auto' | string[] | null;
};
/**
* TaskGroupProperties
Expand Down
1 change: 1 addition & 0 deletions packages/workflowai/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export type RunOptions<Stream extends true | false = false> = {
stream?: Stream;
fetch?: FetchOptions;
privateFields?: ('task_input' | 'task_output' | string)[];
useFallback?: 'never' | 'auto' | string[];
};

export type FileContentType =
Expand Down
69 changes: 69 additions & 0 deletions tests/integration/agent.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -202,4 +202,73 @@ describe('run', () => {
expect(error.errorCode).toBeFalsy();
}
});

it('correctly handles useFallback when passed to the run function', async () => {
const run1Fixture = await readFile(fixturePath('run1.json'), 'utf-8');
mockFetch.mockResponseOnce(run1Fixture);

const result = await run({ animal: 'platypus' }, { useFallback: 'never' });
expect(result.output).toEqual({
is_cute: true,
is_dangerous: true,
explanation_of_reasoning: 'Plat plat',
});

expect(mockFetch.mock.calls.length).toEqual(1);
const req = mockFetch.mock.calls[0][0] as Request;
expect(req.url).toEqual(
'https://run.workflowai.com/v1/_/agents/animal-classification/schemas/4/run'
);
expect(req.method).toEqual('POST');
expect(req.headers.get('Authorization')).toEqual('Bearer hello');
const body = await req.json();
expect(body).toEqual({
version: 'production',
stream: false,
task_input: {
animal: 'platypus',
},
use_cache: 'auto',
use_fallback: 'never',
});
});

it('correctly handles useFallback when passed to the agent', async () => {
const run2 = workflowAI.agent<
AnimalClassificationInput,
AnimalClassificationOutput
>({
id: 'animal-classification',
schemaId: 4,
version: 'production',
useFallback: ['gpt-4o-mini', 'gpt-4o'],
});
const run1Fixture = await readFile(fixturePath('run1.json'), 'utf-8');
mockFetch.mockResponseOnce(run1Fixture);

const result = await run2({ animal: 'platypus' });
expect(result.output).toEqual({
is_cute: true,
is_dangerous: true,
explanation_of_reasoning: 'Plat plat',
});

expect(mockFetch.mock.calls.length).toEqual(1);
const req = mockFetch.mock.calls[0][0] as Request;
expect(req.url).toEqual(
'https://run.workflowai.com/v1/_/agents/animal-classification/schemas/4/run'
);
expect(req.method).toEqual('POST');
expect(req.headers.get('Authorization')).toEqual('Bearer hello');
const body = await req.json();
expect(body).toEqual({
version: 'production',
stream: false,
task_input: {
animal: 'platypus',
},
use_cache: 'auto',
use_fallback: ['gpt-4o-mini', 'gpt-4o'],
});
});
});