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({
|
.call({
|
||||||
searchResults
|
searchResults
|
||||||
})
|
})
|
||||||
|
console.log(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
main()
|
main()
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
25
src/task.ts
25
src/task.ts
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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> {
|
||||||
|
|
|
@ -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> {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Ładowanie…
Reference in New Issue