pull/643/head^2
Travis Fischer 2024-06-01 21:04:13 -05:00
rodzic 839f46097c
commit 8aa53fed71
20 zmienionych plików z 826 dodań i 21783 usunięć

Wyświetl plik

@ -1,4 +1,4 @@
{
"root": true,
"extends": ["@fisch0920/eslint-config", "@fisch0920/eslint-config/node"]
"extends": ["@fisch0920/eslint-config/node"]
}

Wyświetl plik

@ -0,0 +1,24 @@
#!/usr/bin/env node
import 'dotenv/config'
import { openai } from '@ai-sdk/openai'
import { generateText } from 'ai'
import { WeatherClient } from '../../src/index.js'
import { tools } from '../../src/sdks/ai-sdk.js'
async function main() {
const weather = new WeatherClient()
const result = await generateText({
model: openai('gpt-4-turbo'),
tools: tools(weather),
toolChoice: 'required',
prompt:
'What is the weather in San Francisco and what attractions should I visit?'
})
console.log(result.toolResults[0])
}
await main()

Wyświetl plik

@ -7,11 +7,10 @@ import {
createAIRunner,
Msg
} from '@dexaai/dexter'
import { gracefulExit } from 'exit-hook'
import restoreCursor from 'restore-cursor'
import { z } from 'zod'
import { WeatherClient } from '../src/index.js'
import { WeatherClient } from '../../src/index.js'
import { functions } from '../../src/sdks/dexter.js'
/** Get the capital city for a given state. */
const getCapitalCity = createAIFunction(
@ -46,31 +45,14 @@ const getCapitalCity = createAIFunction(
const weather = new WeatherClient()
const fns = [...weather.functions]
console.log('fns', fns)
const getCurrentWeather = weather.functions.get('get_current_weather')!
console.log('get_current_weather', getCurrentWeather)
/** A runner that uses the weather and capital city functions. */
const weatherCapitalRunner = createAIRunner({
chatModel: new ChatModel({ params: { model: 'gpt-4-1106-preview' } }),
functions: [
createAIFunction(
{
...getCurrentWeather.spec,
argsSchema: getCurrentWeather.inputSchema
},
getCurrentWeather.impl
),
getCapitalCity
],
functions: [...functions(weather), getCapitalCity],
systemMessage: `You use functions to answer questions about the weather and capital cities.`
})
async function main() {
restoreCursor()
// Run with a string input
const rString = await weatherCapitalRunner(
`Whats the capital of California and NY and the weather for both?`
@ -88,9 +70,4 @@ async function main() {
console.log('rMessage', rMessage)
}
try {
await main()
} catch (err) {
console.error('unexpected error', err)
gracefulExit(1)
}
await main()

Wyświetl plik

@ -0,0 +1,33 @@
{
"name": "agentic-examples",
"private": true,
"version": "0.1.0",
"description": "TODO",
"author": "Travis Fischer <travis@transitivebullsh.it>",
"license": "MIT",
"repository": {
"type": "git",
"url": "transitive-bullshit/agentic"
},
"packageManager": "pnpm@9.1.4",
"engines": {
"node": ">=18"
},
"type": "module",
"scripts": {
"preinstall": "npx only-allow pnpm",
"build": "tsc",
"clean": "del dist",
"prebuild": "run-s clean",
"pretest": "run-s build",
"test": "run-s test:*",
"test:typecheck": "tsc --noEmit"
},
"dependencies": {
"ai": "^3.1.22",
"@ai-sdk/openai": "^0.0.18",
"@dexaai/dexter": "^2.0.3",
"dotenv": "^16.4.5",
"zod": "^3.23.3"
}
}

Wyświetl plik

@ -0,0 +1,4 @@
{
"extends": "../tsconfig.json",
"include": ["ai-sdk", "dexter"]
}

Wyświetl plik

@ -1,28 +1,32 @@
{
"name": "gptlint",
"name": "@agentic/stdlib",
"private": true,
"version": "0.1.0",
"description": "TODO",
"author": "Travis Fischer <travis@transitivebullsh.it>",
"license": "PROPRIETARY",
"homepage": "https://trywalter.ai",
"license": "MIT",
"repository": {
"type": "git",
"url": "transitive-bullshit/walter"
"url": "transitive-bullshit/agentic"
},
"packageManager": "pnpm@8.15.7",
"packageManager": "pnpm@9.1.4",
"engines": {
"node": ">=18"
},
"type": "module",
"source": "./src/gptlint.ts",
"source": "./src/index.ts",
"types": "./dist/index.d.ts",
"sideEffects": false,
"exports": {
".": {
"types": "./dist/src/index.d.ts",
"import": "./dist/src/index.js",
"default": "./dist/src/index.js"
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"default": "./dist/index.js"
},
"./ai-sdk": {
"types": "./dist/sdks/ai-sdk.d.ts",
"import": "./dist/sdks/ai-sdk.js",
"default": "./dist/sdks/ai-sdk.js"
}
},
"files": [
@ -67,6 +71,7 @@
"@fisch0920/eslint-config": "^1.3.1",
"@total-typescript/ts-reset": "^0.5.1",
"@types/node": "^20.12.7",
"ai": "^3.1.22",
"del-cli": "^5.1.0",
"eslint": "^8.57.0",
"husky": "^9.0.11",
@ -81,6 +86,10 @@
"typescript": "^5.4.5",
"vitest": "2.0.0-beta.3"
},
"optionalDependencies": {
"@dexaai/dexter": "^2.0.3",
"ai": "^3.1.22"
},
"lint-staged": {
"*.{ts,tsx}": [
"eslint --fix",

Plik diff jest za duży Load Diff

Wyświetl plik

@ -0,0 +1,2 @@
packages:
- 'examples'

File diff suppressed because one or more lines are too long

Plik diff jest za duży Load Diff

Wyświetl plik

@ -15,7 +15,7 @@ export class AIFunctionSet implements Iterable<types.AIFunction> {
}
add(fn: types.AIFunction): this {
this._map.set(fn.name, fn)
this._map.set(fn.spec.name, fn)
return this
}
@ -54,6 +54,10 @@ export class AIFunctionSet implements Iterable<types.AIFunction> {
)
}
map<T>(fn: (fn: types.AIFunction) => T): T[] {
return [...this.entries].map(fn)
}
get entries(): IterableIterator<types.AIFunction> {
return this._map.values()
}

Wyświetl plik

@ -58,6 +58,10 @@ export class AIToolSet implements Iterable<types.AITool> {
)
}
map<T>(fn: (fn: types.AITool) => T): T[] {
return [...this.entries].map(fn)
}
get entries(): IterableIterator<types.AITool> {
return this._map.values()
}

Wyświetl plik

@ -8,6 +8,13 @@ import { AIFunctionSet } from './ai-function-set.js'
import { AIToolSet } from './ai-tool-set.js'
import { assert } from './utils.js'
export interface Invocable {
name: string
description?: string
inputSchema: z.AnyZodObject
methodName: string
}
export abstract class AIToolsProvider {
private _tools?: AIToolSet
private _functions?: AIFunctionSet
@ -25,7 +32,7 @@ export abstract class AIToolsProvider {
const metadata = this.constructor[Symbol.metadata]
assert(metadata)
const invocables = (metadata?.invocables as Invocable[]) ?? []
console.log({ metadata, invocables })
// console.log({ metadata, invocables })
const aiFunctions = invocables.map((invocable) => {
const impl = (this as any)[invocable.methodName]?.bind(this)
@ -41,13 +48,6 @@ export abstract class AIToolsProvider {
}
}
export interface Invocable {
name: string
description?: string
inputSchema: z.AnyZodObject
methodName: string
}
export function aiFunction<
This,
InputSchema extends z.SomeZodObject,
@ -87,11 +87,11 @@ export function aiFunction<
inputSchema,
methodName
})
console.log({
name,
methodName,
context
})
// console.log({
// name,
// methodName,
// context
// })
// context.addInitializer(function () {
// ;(this as any)[methodName] = (this as any)[methodName].bind(this)

19
src/sdks/ai-sdk.ts 100644
Wyświetl plik

@ -0,0 +1,19 @@
import { tool } from 'ai'
import type { AIFunctionSet } from '../ai-function-set.js'
import { AIToolsProvider } from '../fns.js'
export function tools(tools: AIToolsProvider | AIFunctionSet) {
const fns = tools instanceof AIToolsProvider ? tools.functions : tools
return Object.fromEntries(
[...fns].map((fn) => [
fn.spec.name,
tool({
description: fn.spec.description,
parameters: fn.inputSchema,
execute: fn.impl
})
])
)
}

19
src/sdks/dexter.ts 100644
Wyświetl plik

@ -0,0 +1,19 @@
import { createAIFunction } from '@dexaai/dexter'
import type { AIFunctionSet } from '../ai-function-set.js'
import { AIToolsProvider } from '../fns.js'
export function functions(input: AIToolsProvider | AIFunctionSet) {
const fns = input instanceof AIToolsProvider ? input.functions : input
return fns.map((fn) =>
createAIFunction(
{
name: fn.spec.name,
description: fn.spec.description,
argsSchema: fn.inputSchema
},
fn.impl
)
)
}

Wyświetl plik

@ -1,5 +1,5 @@
import defaultKy, { type KyInstance } from 'ky'
import * as z from 'zod'
import { z } from 'zod'
import { assert, getEnv } from '../utils.js'

Wyświetl plik

@ -126,18 +126,4 @@ export class WeatherClient extends AIToolsProvider {
})
.json<weatherapi.CurrentWeatherResponse>()
}
async ipInfo(ipOrOptions: string | { q: string }) {
const options =
typeof ipOrOptions === 'string' ? { q: ipOrOptions } : ipOrOptions
return this.ky
.get('ip.json', {
searchParams: {
key: this.apiKey,
...options
}
})
.json<weatherapi.WeatherIPInfoResponse>()
}
}

Wyświetl plik

@ -22,16 +22,19 @@ export interface AIToolSpec {
function: AIFunctionSpec
}
/** The implementation of the function, with arg parsing and validation. */
export type AIFunctionImpl<Return> = Omit<
(input: string | Msg) => MaybePromise<Return>,
'name' | 'toString' | 'arguments' | 'caller' | 'prototype' | 'length'
>
/**
* A function meant to be used with LLM function calling.
*/
export interface AIFunction<
InputSchema extends z.ZodObject<any> = z.ZodObject<any>,
Return = any
> {
/** The implementation of the function, with arg parsing and validation. */
(input: string | Msg): MaybePromise<Return>
> extends AIFunctionImpl<Return> {
/** The Zod schema for the arguments string. */
inputSchema: InputSchema
@ -41,6 +44,7 @@ export interface AIFunction<
/** The function spec for the OpenAI API `functions` property. */
spec: AIFunctionSpec
/** The underlying function implementation without any arg parsing or validation. */
impl: (params: z.infer<InputSchema>) => MaybePromise<Return>
}

Wyświetl plik

@ -25,5 +25,5 @@
"outDir": "dist",
"sourceMap": true
},
"include": ["src", "bin"]
"include": ["src"]
}

Wyświetl plik

@ -2,7 +2,7 @@ import { defineConfig } from 'tsup'
export default defineConfig([
{
entry: ['src/index.ts'],
entry: ['src/index.ts', 'src/sdks/ai-sdk.ts'],
outDir: 'dist',
target: 'node18',
platform: 'node',