kopia lustrzana https://github.com/transitive-bullshit/chatgpt-api
feat: add task id and improve core task design
rodzic
6a96f5429b
commit
cff74009c5
|
@ -39,6 +39,7 @@ async function main() {
|
|||
.call({
|
||||
searchResults
|
||||
})
|
||||
console.log(res)
|
||||
}
|
||||
|
||||
main()
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
"js-tiktoken": "^1.0.6",
|
||||
"jsonrepair": "^3.1.0",
|
||||
"ky": "^0.33.3",
|
||||
"nanoid": "^4.0.2",
|
||||
"openai-fetch": "^1.5.1",
|
||||
"p-map": "^6.0.0",
|
||||
"p-retry": "^5.1.2",
|
||||
|
|
|
@ -32,6 +32,9 @@ dependencies:
|
|||
ky:
|
||||
specifier: ^0.33.3
|
||||
version: 0.33.3
|
||||
nanoid:
|
||||
specifier: ^4.0.2
|
||||
version: 4.0.2
|
||||
openai-fetch:
|
||||
specifier: ^1.5.1
|
||||
version: 1.5.1
|
||||
|
@ -2807,6 +2810,12 @@ packages:
|
|||
thenify-all: 1.6.0
|
||||
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:
|
||||
resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==}
|
||||
dev: true
|
||||
|
|
|
@ -6,6 +6,7 @@ import {
|
|||
HumanFeedbackMechanism,
|
||||
HumanFeedbackMechanismCLI
|
||||
} from './human-feedback'
|
||||
import { defaultIDGeneratorFn } from './utils'
|
||||
|
||||
export class Agentic {
|
||||
// _taskMap: WeakMap<string, BaseTask<any, any>>
|
||||
|
@ -20,6 +21,8 @@ export class Agentic {
|
|||
>
|
||||
protected _defaultHumanFeedbackMechamism?: HumanFeedbackMechanism
|
||||
|
||||
protected _idGeneratorFn: types.IDGeneratorFunction
|
||||
|
||||
constructor(opts: {
|
||||
openai?: types.openai.OpenAIClient
|
||||
anthropic?: types.anthropic.Client
|
||||
|
@ -29,6 +32,7 @@ export class Agentic {
|
|||
'provider' | 'model' | 'modelParams' | 'timeoutMs' | 'retryConfig'
|
||||
>
|
||||
defaultHumanFeedbackMechanism?: HumanFeedbackMechanism
|
||||
idGeneratorFn?: types.IDGeneratorFunction
|
||||
}) {
|
||||
this._openai = opts.openai
|
||||
this._anthropic = opts.anthropic
|
||||
|
@ -54,6 +58,8 @@ export class Agentic {
|
|||
this._defaultHumanFeedbackMechamism =
|
||||
opts.defaultHumanFeedbackMechanism ??
|
||||
new HumanFeedbackMechanismCLI({ agentic: this })
|
||||
|
||||
this._idGeneratorFn = opts.idGeneratorFn ?? defaultIDGeneratorFn
|
||||
}
|
||||
|
||||
public get openai(): types.openai.OpenAIClient | undefined {
|
||||
|
@ -68,6 +74,10 @@ export class Agentic {
|
|||
return this._defaultHumanFeedbackMechamism
|
||||
}
|
||||
|
||||
public get idGeneratorFn(): types.IDGeneratorFunction {
|
||||
return this._idGeneratorFn
|
||||
}
|
||||
|
||||
llm(
|
||||
promptOrChatCompletionParams:
|
||||
| string
|
||||
|
|
|
@ -83,6 +83,10 @@ export abstract class BaseLLM<
|
|||
}
|
||||
}
|
||||
|
||||
public override get name(): string {
|
||||
return `${this._provider}:chat:${this._model}`
|
||||
}
|
||||
|
||||
examples(examples: types.LLMExample[]) {
|
||||
this._examples = examples
|
||||
return this
|
||||
|
|
25
src/task.ts
25
src/task.ts
|
@ -6,9 +6,9 @@ import * as types from '@/types'
|
|||
import { Agentic } from '@/agentic'
|
||||
|
||||
/**
|
||||
* A `Task` is a typed, async function call that may be non-deterministic.
|
||||
*
|
||||
* Invoking a task is equivalent to sampling from a probability distribution.
|
||||
* 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
|
||||
* sampling from a probability distribution.
|
||||
*
|
||||
* Examples of tasks include:
|
||||
* - LLM calls
|
||||
|
@ -23,6 +23,7 @@ export abstract class BaseTask<
|
|||
TOutput extends ZodRawShape | ZodTypeAny = ZodTypeAny
|
||||
> {
|
||||
protected _agentic: Agentic
|
||||
protected _id: string
|
||||
|
||||
protected _timeoutMs?: number
|
||||
protected _retryConfig: types.RetryConfig
|
||||
|
@ -34,21 +35,21 @@ export abstract class BaseTask<
|
|||
retries: 3,
|
||||
strategy: 'default'
|
||||
}
|
||||
this._id = options.id ?? this._agentic.idGeneratorFn()
|
||||
}
|
||||
|
||||
public get agentic(): Agentic {
|
||||
return this._agentic
|
||||
}
|
||||
|
||||
public get id(): string {
|
||||
return this._id
|
||||
}
|
||||
|
||||
public abstract get inputSchema(): TInput
|
||||
public abstract get outputSchema(): TOutput
|
||||
|
||||
// TODO
|
||||
// public abstract get nameForModel(): string
|
||||
// public abstract get nameForHuman(): string
|
||||
|
||||
// public abstract get descForModel(): string
|
||||
// public abstract get descForHuman(): string
|
||||
public abstract get name(): string
|
||||
|
||||
public retryConfig(retryConfig: types.RetryConfig) {
|
||||
this._retryConfig = retryConfig
|
||||
|
@ -83,7 +84,10 @@ export abstract class BaseTask<
|
|||
const ctx: types.TaskCallContext<TInput> = {
|
||||
input,
|
||||
attemptNumber: 0,
|
||||
metadata: {}
|
||||
metadata: {
|
||||
taskName: this.name,
|
||||
taskId: this.id
|
||||
}
|
||||
}
|
||||
|
||||
const result = await pRetry(() => this._call(ctx), {
|
||||
|
@ -93,6 +97,7 @@ export abstract class BaseTask<
|
|||
await Promise.resolve(this._retryConfig.onFailedAttempt(err))
|
||||
}
|
||||
|
||||
// TODO: log this task error
|
||||
ctx.attemptNumber = err.attemptNumber + 1
|
||||
ctx.metadata.error = err
|
||||
|
||||
|
|
|
@ -58,6 +58,10 @@ export class MetaphorSearchTool extends BaseTask<
|
|||
return MetaphorSearchToolOutputSchema
|
||||
}
|
||||
|
||||
public override get name(): string {
|
||||
return 'metaphor-search'
|
||||
}
|
||||
|
||||
protected override async _call(
|
||||
ctx: types.TaskCallContext<typeof MetaphorSearchToolInputSchema>
|
||||
): Promise<MetaphorSearchToolOutput> {
|
||||
|
|
|
@ -63,6 +63,10 @@ export class NovuNotificationTool extends BaseTask<
|
|||
return NovuNotificationToolOutputSchema
|
||||
}
|
||||
|
||||
public override get name(): string {
|
||||
return 'novu'
|
||||
}
|
||||
|
||||
protected override async _call(
|
||||
ctx: types.TaskCallContext<typeof NovuNotificationToolInputSchema>
|
||||
): Promise<NovuNotificationToolOutput> {
|
||||
|
|
|
@ -34,6 +34,7 @@ export interface BaseTaskOptions {
|
|||
|
||||
timeoutMs?: number
|
||||
retryConfig?: RetryConfig
|
||||
id?: string
|
||||
|
||||
// TODO
|
||||
// caching config
|
||||
|
@ -115,8 +116,8 @@ export type TaskError =
|
|||
|
||||
export interface TaskResponseMetadata extends Record<string, any> {
|
||||
// task info
|
||||
// - task name
|
||||
// - task id
|
||||
taskName: string
|
||||
taskId: string
|
||||
|
||||
// execution info
|
||||
success?: boolean
|
||||
|
@ -146,7 +147,9 @@ export interface TaskCallContext<
|
|||
retryMessage?: string
|
||||
|
||||
attemptNumber: number
|
||||
metadata: Partial<TMetadata>
|
||||
metadata: TMetadata
|
||||
}
|
||||
|
||||
export type IDGeneratorFunction = () => string
|
||||
|
||||
// export type ProgressFunction = (partialResponse: ChatMessage) => void
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
import { customAlphabet, urlAlphabet } from 'nanoid'
|
||||
|
||||
import * as types from './types'
|
||||
|
||||
export const extractJSONObjectFromString = (text: string): string | undefined =>
|
||||
text.match(/\{(.|\n)*\}/gm)?.[0]
|
||||
|
||||
|
@ -6,3 +10,6 @@ export const extractJSONArrayFromString = (text: string): string | undefined =>
|
|||
|
||||
export const sleep = (ms: number) =>
|
||||
new Promise((resolve) => setTimeout(resolve, ms))
|
||||
|
||||
export const defaultIDGeneratorFn: types.IDGeneratorFunction =
|
||||
customAlphabet(urlAlphabet)
|
||||
|
|
Ładowanie…
Reference in New Issue