feat: add task id and improve core task design

old-agentic-v1^2
Travis Fischer 2023-06-10 19:59:33 -07:00
rodzic 6a96f5429b
commit cff74009c5
10 zmienionych plików z 61 dodań i 13 usunięć

Wyświetl plik

@ -39,6 +39,7 @@ async function main() {
.call({ .call({
searchResults searchResults
}) })
console.log(res)
} }
main() main()

Wyświetl plik

@ -47,6 +47,7 @@
"js-tiktoken": "^1.0.6", "js-tiktoken": "^1.0.6",
"jsonrepair": "^3.1.0", "jsonrepair": "^3.1.0",
"ky": "^0.33.3", "ky": "^0.33.3",
"nanoid": "^4.0.2",
"openai-fetch": "^1.5.1", "openai-fetch": "^1.5.1",
"p-map": "^6.0.0", "p-map": "^6.0.0",
"p-retry": "^5.1.2", "p-retry": "^5.1.2",

Wyświetl plik

@ -32,6 +32,9 @@ dependencies:
ky: ky:
specifier: ^0.33.3 specifier: ^0.33.3
version: 0.33.3 version: 0.33.3
nanoid:
specifier: ^4.0.2
version: 4.0.2
openai-fetch: openai-fetch:
specifier: ^1.5.1 specifier: ^1.5.1
version: 1.5.1 version: 1.5.1
@ -2807,6 +2810,12 @@ packages:
thenify-all: 1.6.0 thenify-all: 1.6.0
dev: true dev: true
/nanoid@4.0.2:
resolution: {integrity: sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw==}
engines: {node: ^14 || ^16 || >=18}
hasBin: true
dev: false
/natural-compare-lite@1.4.0: /natural-compare-lite@1.4.0:
resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==} resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==}
dev: true dev: true

Wyświetl plik

@ -6,6 +6,7 @@ import {
HumanFeedbackMechanism, HumanFeedbackMechanism,
HumanFeedbackMechanismCLI HumanFeedbackMechanismCLI
} from './human-feedback' } from './human-feedback'
import { defaultIDGeneratorFn } from './utils'
export class Agentic { export class Agentic {
// _taskMap: WeakMap<string, BaseTask<any, any>> // _taskMap: WeakMap<string, BaseTask<any, any>>
@ -20,6 +21,8 @@ export class Agentic {
> >
protected _defaultHumanFeedbackMechamism?: HumanFeedbackMechanism protected _defaultHumanFeedbackMechamism?: HumanFeedbackMechanism
protected _idGeneratorFn: types.IDGeneratorFunction
constructor(opts: { constructor(opts: {
openai?: types.openai.OpenAIClient openai?: types.openai.OpenAIClient
anthropic?: types.anthropic.Client anthropic?: types.anthropic.Client
@ -29,6 +32,7 @@ export class Agentic {
'provider' | 'model' | 'modelParams' | 'timeoutMs' | 'retryConfig' 'provider' | 'model' | 'modelParams' | 'timeoutMs' | 'retryConfig'
> >
defaultHumanFeedbackMechanism?: HumanFeedbackMechanism defaultHumanFeedbackMechanism?: HumanFeedbackMechanism
idGeneratorFn?: types.IDGeneratorFunction
}) { }) {
this._openai = opts.openai this._openai = opts.openai
this._anthropic = opts.anthropic this._anthropic = opts.anthropic
@ -54,6 +58,8 @@ export class Agentic {
this._defaultHumanFeedbackMechamism = this._defaultHumanFeedbackMechamism =
opts.defaultHumanFeedbackMechanism ?? opts.defaultHumanFeedbackMechanism ??
new HumanFeedbackMechanismCLI({ agentic: this }) new HumanFeedbackMechanismCLI({ agentic: this })
this._idGeneratorFn = opts.idGeneratorFn ?? defaultIDGeneratorFn
} }
public get openai(): types.openai.OpenAIClient | undefined { public get openai(): types.openai.OpenAIClient | undefined {
@ -68,6 +74,10 @@ export class Agentic {
return this._defaultHumanFeedbackMechamism return this._defaultHumanFeedbackMechamism
} }
public get idGeneratorFn(): types.IDGeneratorFunction {
return this._idGeneratorFn
}
llm( llm(
promptOrChatCompletionParams: promptOrChatCompletionParams:
| string | string

Wyświetl plik

@ -83,6 +83,10 @@ export abstract class BaseLLM<
} }
} }
public override get name(): string {
return `${this._provider}:chat:${this._model}`
}
examples(examples: types.LLMExample[]) { examples(examples: types.LLMExample[]) {
this._examples = examples this._examples = examples
return this return this

Wyświetl plik

@ -6,9 +6,9 @@ import * as types from '@/types'
import { Agentic } from '@/agentic' import { Agentic } from '@/agentic'
/** /**
* A `Task` is a typed, async function call that may be non-deterministic. * A `Task` is an async function call that may be non-deterministic. It has
* * structured input and structured output. Invoking a task is equivalent to
* Invoking a task is equivalent to sampling from a probability distribution. * sampling from a probability distribution.
* *
* Examples of tasks include: * Examples of tasks include:
* - LLM calls * - LLM calls
@ -23,6 +23,7 @@ export abstract class BaseTask<
TOutput extends ZodRawShape | ZodTypeAny = ZodTypeAny TOutput extends ZodRawShape | ZodTypeAny = ZodTypeAny
> { > {
protected _agentic: Agentic protected _agentic: Agentic
protected _id: string
protected _timeoutMs?: number protected _timeoutMs?: number
protected _retryConfig: types.RetryConfig protected _retryConfig: types.RetryConfig
@ -34,21 +35,21 @@ export abstract class BaseTask<
retries: 3, retries: 3,
strategy: 'default' strategy: 'default'
} }
this._id = options.id ?? this._agentic.idGeneratorFn()
} }
public get agentic(): Agentic { public get agentic(): Agentic {
return this._agentic return this._agentic
} }
public get id(): string {
return this._id
}
public abstract get inputSchema(): TInput public abstract get inputSchema(): TInput
public abstract get outputSchema(): TOutput public abstract get outputSchema(): TOutput
// TODO public abstract get name(): string
// public abstract get nameForModel(): string
// public abstract get nameForHuman(): string
// public abstract get descForModel(): string
// public abstract get descForHuman(): string
public retryConfig(retryConfig: types.RetryConfig) { public retryConfig(retryConfig: types.RetryConfig) {
this._retryConfig = retryConfig this._retryConfig = retryConfig
@ -83,7 +84,10 @@ export abstract class BaseTask<
const ctx: types.TaskCallContext<TInput> = { const ctx: types.TaskCallContext<TInput> = {
input, input,
attemptNumber: 0, attemptNumber: 0,
metadata: {} metadata: {
taskName: this.name,
taskId: this.id
}
} }
const result = await pRetry(() => this._call(ctx), { const result = await pRetry(() => this._call(ctx), {
@ -93,6 +97,7 @@ export abstract class BaseTask<
await Promise.resolve(this._retryConfig.onFailedAttempt(err)) await Promise.resolve(this._retryConfig.onFailedAttempt(err))
} }
// TODO: log this task error
ctx.attemptNumber = err.attemptNumber + 1 ctx.attemptNumber = err.attemptNumber + 1
ctx.metadata.error = err ctx.metadata.error = err

Wyświetl plik

@ -58,6 +58,10 @@ export class MetaphorSearchTool extends BaseTask<
return MetaphorSearchToolOutputSchema return MetaphorSearchToolOutputSchema
} }
public override get name(): string {
return 'metaphor-search'
}
protected override async _call( protected override async _call(
ctx: types.TaskCallContext<typeof MetaphorSearchToolInputSchema> ctx: types.TaskCallContext<typeof MetaphorSearchToolInputSchema>
): Promise<MetaphorSearchToolOutput> { ): Promise<MetaphorSearchToolOutput> {

Wyświetl plik

@ -63,6 +63,10 @@ export class NovuNotificationTool extends BaseTask<
return NovuNotificationToolOutputSchema return NovuNotificationToolOutputSchema
} }
public override get name(): string {
return 'novu'
}
protected override async _call( protected override async _call(
ctx: types.TaskCallContext<typeof NovuNotificationToolInputSchema> ctx: types.TaskCallContext<typeof NovuNotificationToolInputSchema>
): Promise<NovuNotificationToolOutput> { ): Promise<NovuNotificationToolOutput> {

Wyświetl plik

@ -34,6 +34,7 @@ export interface BaseTaskOptions {
timeoutMs?: number timeoutMs?: number
retryConfig?: RetryConfig retryConfig?: RetryConfig
id?: string
// TODO // TODO
// caching config // caching config
@ -115,8 +116,8 @@ export type TaskError =
export interface TaskResponseMetadata extends Record<string, any> { export interface TaskResponseMetadata extends Record<string, any> {
// task info // task info
// - task name taskName: string
// - task id taskId: string
// execution info // execution info
success?: boolean success?: boolean
@ -146,7 +147,9 @@ export interface TaskCallContext<
retryMessage?: string retryMessage?: string
attemptNumber: number attemptNumber: number
metadata: Partial<TMetadata> metadata: TMetadata
} }
export type IDGeneratorFunction = () => string
// export type ProgressFunction = (partialResponse: ChatMessage) => void // export type ProgressFunction = (partialResponse: ChatMessage) => void

Wyświetl plik

@ -1,3 +1,7 @@
import { customAlphabet, urlAlphabet } from 'nanoid'
import * as types from './types'
export const extractJSONObjectFromString = (text: string): string | undefined => export const extractJSONObjectFromString = (text: string): string | undefined =>
text.match(/\{(.|\n)*\}/gm)?.[0] text.match(/\{(.|\n)*\}/gm)?.[0]
@ -6,3 +10,6 @@ export const extractJSONArrayFromString = (text: string): string | undefined =>
export const sleep = (ms: number) => export const sleep = (ms: number) =>
new Promise((resolve) => setTimeout(resolve, ms)) new Promise((resolve) => setTimeout(resolve, ms))
export const defaultIDGeneratorFn: types.IDGeneratorFunction =
customAlphabet(urlAlphabet)