kopia lustrzana https://github.com/transitive-bullshit/chatgpt-api
feat: refactoring core
rodzic
8c7b34f0dc
commit
ed4ea41c51
|
@ -6,4 +6,3 @@
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
OPENAI_API_KEY=
|
OPENAI_API_KEY=
|
||||||
METAPHOR_API_KEY=
|
|
|
@ -1,11 +1,9 @@
|
||||||
import dotenv from 'dotenv-safe'
|
import 'dotenv/config'
|
||||||
import { OpenAIClient } from 'openai-fetch'
|
import { OpenAIClient } from 'openai-fetch'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
|
|
||||||
import { Agentic } from '../src'
|
import { Agentic } from '../src'
|
||||||
|
|
||||||
dotenv.config()
|
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
const openai = new OpenAIClient({ apiKey: process.env.OPENAI_API_KEY! })
|
const openai = new OpenAIClient({ apiKey: process.env.OPENAI_API_KEY! })
|
||||||
const $ = new Agentic({ openai })
|
const $ = new Agentic({ openai })
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
import dotenv from 'dotenv-safe'
|
import 'dotenv/config'
|
||||||
import { OpenAIClient } from 'openai-fetch'
|
import { OpenAIClient } from 'openai-fetch'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
|
|
||||||
import { Agentic } from '../src/llm'
|
import { Agentic } from '../src'
|
||||||
import { getProblems } from './fixtures/calc'
|
import { getProblems } from './fixtures/calc'
|
||||||
|
|
||||||
dotenv.config()
|
|
||||||
|
|
||||||
export async function calcEval() {
|
export async function calcEval() {
|
||||||
const openai = new OpenAIClient({ apiKey: process.env.OPENAI_API_KEY! })
|
const openai = new OpenAIClient({ apiKey: process.env.OPENAI_API_KEY! })
|
||||||
const $ = new Agentic({ openai })
|
const $ = new Agentic({ openai })
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
import dotenv from 'dotenv-safe'
|
import 'dotenv/config'
|
||||||
import { OpenAIClient } from 'openai-fetch'
|
import { OpenAIClient } from 'openai-fetch'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
|
|
||||||
import { Agentic } from '../src'
|
import { Agentic } from '../src'
|
||||||
|
|
||||||
dotenv.config()
|
|
||||||
|
|
||||||
export async function equationProducer() {
|
export async function equationProducer() {
|
||||||
const openai = new OpenAIClient({ apiKey: process.env.OPENAI_API_KEY! })
|
const openai = new OpenAIClient({ apiKey: process.env.OPENAI_API_KEY! })
|
||||||
const $ = new Agentic({ openai })
|
const $ = new Agentic({ openai })
|
||||||
|
@ -31,11 +29,13 @@ export async function equationProducer() {
|
||||||
`You are an expert math teacher. Think step by step, and give me the equation for the following math problem: \n\n{{question}}`
|
`You are an expert math teacher. Think step by step, and give me the equation for the following math problem: \n\n{{question}}`
|
||||||
)
|
)
|
||||||
.input(z.object({ question: z.string() }))
|
.input(z.object({ question: z.string() }))
|
||||||
.output({
|
.output(
|
||||||
|
z.object({
|
||||||
question: z.string(),
|
question: z.string(),
|
||||||
equation: z.string(),
|
equation: z.string(),
|
||||||
predictedAnswer: z.number()
|
predictedAnswer: z.number()
|
||||||
})
|
})
|
||||||
|
)
|
||||||
.examples(examples)
|
.examples(examples)
|
||||||
// .assert(
|
// .assert(
|
||||||
// (output) =>
|
// (output) =>
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
import dotenv from 'dotenv-safe'
|
import 'dotenv/config'
|
||||||
import { OpenAIClient } from 'openai-fetch'
|
import { OpenAIClient } from 'openai-fetch'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
|
|
||||||
import { Agentic } from '../src'
|
import { Agentic } from '../src'
|
||||||
|
|
||||||
dotenv.config()
|
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
const openai = new OpenAIClient({ apiKey: process.env.OPENAI_API_KEY! })
|
const openai = new OpenAIClient({ apiKey: process.env.OPENAI_API_KEY! })
|
||||||
const ai = new Agentic({ openai })
|
const ai = new Agentic({ openai })
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
import dotenv from 'dotenv-safe'
|
import 'dotenv/config'
|
||||||
import { OpenAIClient } from 'openai-fetch'
|
import { OpenAIClient } from 'openai-fetch'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
|
|
||||||
import { Agentic } from '../src'
|
import { Agentic } from '../src'
|
||||||
import { summaryAgent } from './summary'
|
import { summaryAgent } from './summary'
|
||||||
|
|
||||||
dotenv.config()
|
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
const openai = new OpenAIClient({ apiKey: process.env.OPENAI_API_KEY! })
|
const openai = new OpenAIClient({ apiKey: process.env.OPENAI_API_KEY! })
|
||||||
const $ = new Agentic({ openai })
|
const $ = new Agentic({ openai })
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
import dotenv from 'dotenv-safe'
|
import 'dotenv/config'
|
||||||
import { OpenAIClient } from 'openai-fetch'
|
import { OpenAIClient } from 'openai-fetch'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
|
|
||||||
import { Agentic } from '../src'
|
import { Agentic } from '../src'
|
||||||
|
|
||||||
dotenv.config()
|
|
||||||
|
|
||||||
export async function main() {
|
export async function main() {
|
||||||
const openai = new OpenAIClient({ apiKey: process.env.OPENAI_API_KEY! })
|
const openai = new OpenAIClient({ apiKey: process.env.OPENAI_API_KEY! })
|
||||||
const $ = new Agentic({ openai })
|
const $ = new Agentic({ openai })
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
import dotenv from 'dotenv-safe'
|
import 'dotenv/config'
|
||||||
import { OpenAIClient } from 'openai-fetch'
|
import { OpenAIClient } from 'openai-fetch'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
|
|
||||||
import { Agentic, MetaphorSearchTool } from '../src'
|
import { Agentic, MetaphorSearchTool } from '../src'
|
||||||
|
|
||||||
dotenv.config()
|
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
const metaphorSearch = new MetaphorSearchTool()
|
const metaphorSearch = new MetaphorSearchTool()
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
import dotenv from 'dotenv-safe'
|
import 'dotenv/config'
|
||||||
import { OpenAIClient } from 'openai-fetch'
|
import { OpenAIClient } from 'openai-fetch'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
|
|
||||||
import { Agentic } from '../src'
|
import { Agentic } from '../src'
|
||||||
|
|
||||||
dotenv.config()
|
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
const openai = new OpenAIClient({ apiKey: process.env.OPENAI_API_KEY! })
|
const openai = new OpenAIClient({ apiKey: process.env.OPENAI_API_KEY! })
|
||||||
const $ = new Agentic({ openai })
|
const $ = new Agentic({ openai })
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
import dotenv from 'dotenv-safe'
|
import 'dotenv/config'
|
||||||
import { OpenAIClient } from 'openai-fetch'
|
import { OpenAIClient } from 'openai-fetch'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
|
|
||||||
import { Agentic } from '../src'
|
import { Agentic } from '../src'
|
||||||
|
|
||||||
dotenv.config()
|
|
||||||
|
|
||||||
export async function main() {
|
export async function main() {
|
||||||
const openai = new OpenAIClient({ apiKey: process.env.OPENAI_API_KEY! })
|
const openai = new OpenAIClient({ apiKey: process.env.OPENAI_API_KEY! })
|
||||||
const $ = new Agentic({ openai })
|
const $ = new Agentic({ openai })
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
import dotenv from 'dotenv-safe'
|
import 'dotenv/config'
|
||||||
import { OpenAIClient } from 'openai-fetch'
|
import { OpenAIClient } from 'openai-fetch'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
|
|
||||||
import { Agentic, MetaphorSearchTool } from '../src'
|
import { Agentic, MetaphorSearchTool } from '../src'
|
||||||
|
|
||||||
dotenv.config()
|
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
const openai = new OpenAIClient({ apiKey: process.env.OPENAI_API_KEY! })
|
const openai = new OpenAIClient({ apiKey: process.env.OPENAI_API_KEY! })
|
||||||
const $ = new Agentic({ openai })
|
const $ = new Agentic({ openai })
|
||||||
|
|
|
@ -35,9 +35,9 @@
|
||||||
"test:prettier": "prettier '**/*.{js,jsx,ts,tsx}' --check"
|
"test:prettier": "prettier '**/*.{js,jsx,ts,tsx}' --check"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@dqbd/tiktoken": "^1.0.7",
|
"dotenv": "^16.1.3",
|
||||||
"dotenv-safe": "^8.2.0",
|
|
||||||
"handlebars": "^4.7.7",
|
"handlebars": "^4.7.7",
|
||||||
|
"js-tiktoken": "^1.0.6",
|
||||||
"jsonrepair": "^3.1.0",
|
"jsonrepair": "^3.1.0",
|
||||||
"ky": "^0.33.3",
|
"ky": "^0.33.3",
|
||||||
"openai-fetch": "^1.3.0",
|
"openai-fetch": "^1.3.0",
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
lockfileVersion: '6.0'
|
lockfileVersion: '6.0'
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
'@dqbd/tiktoken':
|
dotenv:
|
||||||
specifier: ^1.0.7
|
specifier: ^16.1.3
|
||||||
version: 1.0.7
|
version: 16.1.3
|
||||||
dotenv-safe:
|
|
||||||
specifier: ^8.2.0
|
|
||||||
version: 8.2.0
|
|
||||||
handlebars:
|
handlebars:
|
||||||
specifier: ^4.7.7
|
specifier: ^4.7.7
|
||||||
version: 4.7.7
|
version: 4.7.7
|
||||||
|
js-tiktoken:
|
||||||
|
specifier: ^1.0.6
|
||||||
|
version: 1.0.6
|
||||||
jsonrepair:
|
jsonrepair:
|
||||||
specifier: ^3.1.0
|
specifier: ^3.1.0
|
||||||
version: 3.1.0
|
version: 3.1.0
|
||||||
|
@ -192,10 +192,6 @@ packages:
|
||||||
to-fast-properties: 2.0.0
|
to-fast-properties: 2.0.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@dqbd/tiktoken@1.0.7:
|
|
||||||
resolution: {integrity: sha512-bhR5k5W+8GLzysjk8zTMVygQZsgvf7W1F0IlL4ZQ5ugjo5rCyiwGM5d8DYriXspytfu98tv59niang3/T+FoDw==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@esbuild-kit/cjs-loader@2.4.2:
|
/@esbuild-kit/cjs-loader@2.4.2:
|
||||||
resolution: {integrity: sha512-BDXFbYOJzT/NBEtp71cvsrGPwGAMGRB/349rwKuoxNSiKjPraNNnlK6MIIabViCjqZugu6j+xeMDlEkWdHHJSg==}
|
resolution: {integrity: sha512-BDXFbYOJzT/NBEtp71cvsrGPwGAMGRB/349rwKuoxNSiKjPraNNnlK6MIIabViCjqZugu6j+xeMDlEkWdHHJSg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -686,6 +682,10 @@ packages:
|
||||||
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
|
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/base64-js@1.5.1:
|
||||||
|
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/binary-extensions@2.2.0:
|
/binary-extensions@2.2.0:
|
||||||
resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
|
resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
@ -1024,15 +1024,9 @@ packages:
|
||||||
path-type: 4.0.0
|
path-type: 4.0.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/dotenv-safe@8.2.0:
|
/dotenv@16.1.3:
|
||||||
resolution: {integrity: sha512-uWwWWdUQkSs5a3mySDB22UtNwyEYi0JtEQu+vDzIqr9OjbDdC2Ip13PnSpi/fctqlYmzkxCeabiyCAOROuAIaA==}
|
resolution: {integrity: sha512-FYssxsmCTtKL72fGBSvb1K9dRz0/VZeWqFme/vSb7r7323x4CRaHu4LvQ5JG3+s6yt2YPbBrkpiEODktfyjI9A==}
|
||||||
dependencies:
|
engines: {node: '>=12'}
|
||||||
dotenv: 8.6.0
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/dotenv@8.6.0:
|
|
||||||
resolution: {integrity: sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/eastasianwidth@0.2.0:
|
/eastasianwidth@0.2.0:
|
||||||
|
@ -1730,6 +1724,12 @@ packages:
|
||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/js-tiktoken@1.0.6:
|
||||||
|
resolution: {integrity: sha512-lxHntEupgjWvSh37WxpAW4XN6UBXBtFJOpZZq5HN5oNjDfN7L/iJhHOKjyL/DFtuYXUwn5jfTciLtOWpgQmHjQ==}
|
||||||
|
dependencies:
|
||||||
|
base64-js: 1.5.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
/js-tokens@4.0.0:
|
/js-tokens@4.0.0:
|
||||||
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
|
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
46
src/llm.ts
46
src/llm.ts
|
@ -1,5 +1,6 @@
|
||||||
import { jsonrepair } from 'jsonrepair'
|
import { jsonrepair } from 'jsonrepair'
|
||||||
import { dedent } from 'ts-dedent'
|
import { dedent } from 'ts-dedent'
|
||||||
|
import { type SetRequired } from 'type-fest'
|
||||||
import { ZodRawShape, ZodTypeAny, z } from 'zod'
|
import { ZodRawShape, ZodTypeAny, z } from 'zod'
|
||||||
import { printNode, zodToTs } from 'zod-to-ts'
|
import { printNode, zodToTs } from 'zod-to-ts'
|
||||||
|
|
||||||
|
@ -12,18 +13,29 @@ import {
|
||||||
} from './utils'
|
} from './utils'
|
||||||
|
|
||||||
export abstract class BaseLLMCallBuilder<
|
export abstract class BaseLLMCallBuilder<
|
||||||
TInput extends ZodRawShape | ZodTypeAny = ZodTypeAny,
|
TInput extends ZodRawShape | ZodTypeAny = z.ZodVoid,
|
||||||
TOutput extends ZodRawShape | ZodTypeAny = z.ZodType<string>,
|
TOutput extends ZodRawShape | ZodTypeAny = z.ZodType<string>,
|
||||||
TModelParams extends Record<string, any> = Record<string, any>
|
TModelParams extends Record<string, any> = Record<string, any>
|
||||||
> extends BaseTaskCallBuilder<TInput, TOutput> {
|
> extends BaseTaskCallBuilder<TInput, TOutput> {
|
||||||
|
protected _inputSchema: TInput | undefined
|
||||||
|
protected _outputSchema: TOutput | undefined
|
||||||
|
|
||||||
protected _provider: string
|
protected _provider: string
|
||||||
protected _model: string
|
protected _model: string
|
||||||
protected _modelParams: TModelParams
|
protected _modelParams: TModelParams | undefined
|
||||||
protected _examples: types.LLMExample[]
|
protected _examples: types.LLMExample[] | undefined
|
||||||
|
|
||||||
constructor(options: types.BaseLLMOptions<TInput, TOutput, TModelParams>) {
|
constructor(
|
||||||
|
options: SetRequired<
|
||||||
|
types.BaseLLMOptions<TInput, TOutput, TModelParams>,
|
||||||
|
'provider' | 'model'
|
||||||
|
>
|
||||||
|
) {
|
||||||
super(options)
|
super(options)
|
||||||
|
|
||||||
|
this._inputSchema = options.inputSchema
|
||||||
|
this._outputSchema = options.outputSchema
|
||||||
|
|
||||||
this._provider = options.provider
|
this._provider = options.provider
|
||||||
this._model = options.model
|
this._model = options.model
|
||||||
this._modelParams = options.modelParams
|
this._modelParams = options.modelParams
|
||||||
|
@ -48,6 +60,23 @@ export abstract class BaseLLMCallBuilder<
|
||||||
return this as unknown as BaseLLMCallBuilder<TInput, U, TModelParams>
|
return this as unknown as BaseLLMCallBuilder<TInput, U, TModelParams>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override get inputSchema(): TInput {
|
||||||
|
if (this._inputSchema) {
|
||||||
|
return this._inputSchema
|
||||||
|
} else {
|
||||||
|
return z.void() as TInput
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override get outputSchema(): TOutput {
|
||||||
|
if (this._outputSchema) {
|
||||||
|
return this._outputSchema
|
||||||
|
} else {
|
||||||
|
// TODO: improve typing
|
||||||
|
return z.string() as unknown as TOutput
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
examples(examples: types.LLMExample[]) {
|
examples(examples: types.LLMExample[]) {
|
||||||
this._examples = examples
|
this._examples = examples
|
||||||
return this
|
return this
|
||||||
|
@ -56,7 +85,7 @@ export abstract class BaseLLMCallBuilder<
|
||||||
modelParams(params: Partial<TModelParams>) {
|
modelParams(params: Partial<TModelParams>) {
|
||||||
// We assume that modelParams does not include nested objects.
|
// We assume that modelParams does not include nested objects.
|
||||||
// If it did, we would need to do a deep merge.
|
// If it did, we would need to do a deep merge.
|
||||||
this._modelParams = Object.assign({}, this._modelParams, params)
|
this._modelParams = { ...this._modelParams, ...params } as TModelParams
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,7 +104,12 @@ export abstract class BaseChatModelBuilder<
|
||||||
> extends BaseLLMCallBuilder<TInput, TOutput, TModelParams> {
|
> extends BaseLLMCallBuilder<TInput, TOutput, TModelParams> {
|
||||||
_messages: types.ChatMessage[]
|
_messages: types.ChatMessage[]
|
||||||
|
|
||||||
constructor(options: types.ChatModelOptions<TInput, TOutput, TModelParams>) {
|
constructor(
|
||||||
|
options: SetRequired<
|
||||||
|
types.ChatModelOptions<TInput, TOutput, TModelParams>,
|
||||||
|
'provider' | 'model' | 'messages'
|
||||||
|
>
|
||||||
|
) {
|
||||||
super(options)
|
super(options)
|
||||||
|
|
||||||
this._messages = options.messages
|
this._messages = options.messages
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
import test from 'ava'
|
||||||
|
import { OpenAIClient } from 'openai-fetch'
|
||||||
|
import { z } from 'zod'
|
||||||
|
|
||||||
|
import { OpenAIChatModelBuilder } from './openai'
|
||||||
|
|
||||||
|
const client = new OpenAIClient({ apiKey: process.env.OPENAI_API_KEY! })
|
||||||
|
|
||||||
|
test('OpenAIChatModel ⇒ json output', async (t) => {
|
||||||
|
const builder = new OpenAIChatModelBuilder(client, {
|
||||||
|
messages: [
|
||||||
|
{
|
||||||
|
role: 'user',
|
||||||
|
content: 'generate fake data'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}).output(z.object({ foo: z.string(), bar: z.number() }))
|
||||||
|
|
||||||
|
const result = await builder.call()
|
||||||
|
type verify = Expect<
|
||||||
|
Equal<
|
||||||
|
typeof result,
|
||||||
|
{
|
||||||
|
foo: string
|
||||||
|
bar: number
|
||||||
|
}
|
||||||
|
>
|
||||||
|
>
|
||||||
|
})
|
||||||
|
|
||||||
|
// Ensure parsed results are typed correctly
|
||||||
|
// https://github.com/total-typescript/zod-tutorial/blob/main/src/helpers/type-utils.ts
|
||||||
|
type Expect<T extends true> = T
|
||||||
|
type Equal<X, Y> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y
|
||||||
|
? 1
|
||||||
|
: 2
|
||||||
|
? true
|
||||||
|
: false
|
|
@ -1,13 +1,13 @@
|
||||||
import type { SetRequired } from 'type-fest'
|
import { type SetRequired } from 'type-fest'
|
||||||
import { ZodRawShape, ZodTypeAny, z } from 'zod'
|
import { ZodTypeAny, z } from 'zod'
|
||||||
|
|
||||||
import * as types from './types'
|
import * as types from './types'
|
||||||
import { defaultOpenAIModel } from './constants'
|
import { defaultOpenAIModel } from './constants'
|
||||||
import { BaseChatModelBuilder } from './llm'
|
import { BaseChatModelBuilder } from './llm'
|
||||||
|
|
||||||
export class OpenAIChatModelBuilder<
|
export class OpenAIChatModelBuilder<
|
||||||
TInput extends ZodRawShape | ZodTypeAny = ZodTypeAny,
|
TInput extends ZodTypeAny = ZodTypeAny,
|
||||||
TOutput extends ZodRawShape | ZodTypeAny = z.ZodType<string>
|
TOutput extends ZodTypeAny = z.ZodType<string>
|
||||||
> extends BaseChatModelBuilder<
|
> extends BaseChatModelBuilder<
|
||||||
TInput,
|
TInput,
|
||||||
TOutput,
|
TOutput,
|
||||||
|
@ -39,8 +39,8 @@ export class OpenAIChatModelBuilder<
|
||||||
types.BaseChatCompletionResponse<types.openai.ChatCompletionResponse>
|
types.BaseChatCompletionResponse<types.openai.ChatCompletionResponse>
|
||||||
> {
|
> {
|
||||||
return this._client.createChatCompletion({
|
return this._client.createChatCompletion({
|
||||||
model: this._model,
|
|
||||||
...this._modelParams,
|
...this._modelParams,
|
||||||
|
model: this._model,
|
||||||
messages
|
messages
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
23
src/task.ts
23
src/task.ts
|
@ -1,3 +1,4 @@
|
||||||
|
import { type SetRequired } from 'type-fest'
|
||||||
import { ZodRawShape, ZodTypeAny, z } from 'zod'
|
import { ZodRawShape, ZodTypeAny, z } from 'zod'
|
||||||
|
|
||||||
import * as types from './types'
|
import * as types from './types'
|
||||||
|
@ -15,32 +16,24 @@ export abstract class BaseTaskCallBuilder<
|
||||||
TInput extends ZodRawShape | ZodTypeAny = ZodTypeAny,
|
TInput extends ZodRawShape | ZodTypeAny = ZodTypeAny,
|
||||||
TOutput extends ZodRawShape | ZodTypeAny = z.ZodTypeAny
|
TOutput extends ZodRawShape | ZodTypeAny = z.ZodTypeAny
|
||||||
> {
|
> {
|
||||||
protected _inputSchema: TInput
|
protected _timeoutMs: number | undefined
|
||||||
protected _outputSchema: TOutput
|
protected _retryConfig: types.RetryConfig | undefined
|
||||||
protected _timeoutMs: number
|
|
||||||
protected _retryConfig: types.RetryConfig
|
|
||||||
|
|
||||||
constructor(options: types.BaseTaskOptions<TInput, TOutput>) {
|
constructor(options: types.BaseTaskOptions) {
|
||||||
this._inputSchema = options.inputSchema
|
|
||||||
this._outputSchema = options.outputSchema
|
|
||||||
this._timeoutMs = options.timeoutMs
|
this._timeoutMs = options.timeoutMs
|
||||||
this._retryConfig = options.retryConfig
|
this._retryConfig = options.retryConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
public get inputSchema(): TInput {
|
public abstract get inputSchema(): TInput
|
||||||
return this._inputSchema
|
|
||||||
}
|
|
||||||
|
|
||||||
public get outputSchema(): TOutput {
|
public abstract get outputSchema(): TOutput
|
||||||
return this._outputSchema
|
|
||||||
}
|
|
||||||
|
|
||||||
retry(retryConfig: types.RetryConfig) {
|
public retryConfig(retryConfig: types.RetryConfig) {
|
||||||
this._retryConfig = retryConfig
|
this._retryConfig = retryConfig
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract call(
|
public abstract call(
|
||||||
input?: types.ParsedData<TInput>
|
input?: types.ParsedData<TInput>
|
||||||
): Promise<types.ParsedData<TOutput>>
|
): Promise<types.ParsedData<TOutput>>
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { encoding_for_model } from '@dqbd/tiktoken'
|
import { getEncoding, getEncodingNameForModel } from 'js-tiktoken'
|
||||||
|
|
||||||
export function getTokenizerForModel(model: string) {
|
export function getTokenizerForModel(model: string) {
|
||||||
return encoding_for_model(model as any)
|
const encodingName = getEncodingNameForModel(model as any)
|
||||||
|
return getEncoding(encodingName)
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,18 +40,25 @@ export class MetaphorSearchTool extends BaseTaskCallBuilder<
|
||||||
metaphorClient?: MetaphorClient
|
metaphorClient?: MetaphorClient
|
||||||
} = {}) {
|
} = {}) {
|
||||||
super({
|
super({
|
||||||
inputSchema: MetaphorSearchToolInputSchema,
|
// TODO
|
||||||
outputSchema: MetaphorSearchToolOutputSchema
|
|
||||||
})
|
})
|
||||||
|
|
||||||
this._metaphorClient = metaphorClient
|
this._metaphorClient = metaphorClient
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override get inputSchema() {
|
||||||
|
return MetaphorSearchToolInputSchema
|
||||||
|
}
|
||||||
|
|
||||||
|
public override get outputSchema() {
|
||||||
|
return MetaphorSearchToolOutputSchema
|
||||||
|
}
|
||||||
|
|
||||||
override async call(
|
override async call(
|
||||||
input: MetaphorSearchToolInput
|
input: MetaphorSearchToolInput
|
||||||
): Promise<MetaphorSearchToolOutput> {
|
): Promise<MetaphorSearchToolOutput> {
|
||||||
// TODO: handle errors gracefully
|
// TODO: handle errors gracefully
|
||||||
input = this._inputSchema.parse(input)
|
input = this.inputSchema.parse(input)
|
||||||
|
|
||||||
return this._metaphorClient.search({
|
return this._metaphorClient.search({
|
||||||
query: input.query,
|
query: input.query,
|
||||||
|
|
13
src/types.ts
13
src/types.ts
|
@ -24,13 +24,7 @@ export type SafeParsedData<T extends ZodRawShape | ZodTypeAny> =
|
||||||
? SafeParseReturnType<ZodObject<T>, ParsedData<T>>
|
? SafeParseReturnType<ZodObject<T>, ParsedData<T>>
|
||||||
: never
|
: never
|
||||||
|
|
||||||
export interface BaseTaskOptions<
|
export interface BaseTaskOptions {
|
||||||
TInput extends ZodRawShape | ZodTypeAny = ZodTypeAny,
|
|
||||||
TOutput extends ZodRawShape | ZodTypeAny = z.ZodType<string>
|
|
||||||
> {
|
|
||||||
inputSchema?: TInput
|
|
||||||
outputSchema?: TOutput
|
|
||||||
|
|
||||||
timeoutMs?: number
|
timeoutMs?: number
|
||||||
retryConfig?: RetryConfig
|
retryConfig?: RetryConfig
|
||||||
|
|
||||||
|
@ -44,7 +38,10 @@ export interface BaseLLMOptions<
|
||||||
TInput extends ZodRawShape | ZodTypeAny = ZodTypeAny,
|
TInput extends ZodRawShape | ZodTypeAny = ZodTypeAny,
|
||||||
TOutput extends ZodRawShape | ZodTypeAny = z.ZodType<string>,
|
TOutput extends ZodRawShape | ZodTypeAny = z.ZodType<string>,
|
||||||
TModelParams extends Record<string, any> = Record<string, any>
|
TModelParams extends Record<string, any> = Record<string, any>
|
||||||
> extends BaseTaskOptions<TInput, TOutput> {
|
> extends BaseTaskOptions {
|
||||||
|
inputSchema?: TInput
|
||||||
|
outputSchema?: TOutput
|
||||||
|
|
||||||
provider?: string
|
provider?: string
|
||||||
model?: string
|
model?: string
|
||||||
modelParams?: TModelParams
|
modelParams?: TModelParams
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
"lib": ["esnext"],
|
"lib": ["esnext"],
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"strict": false,
|
"strict": true,
|
||||||
|
"noImplicitAny": false,
|
||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"module": "esnext",
|
"module": "esnext",
|
||||||
|
|
Ładowanie…
Reference in New Issue