diff --git a/examples/ai-sdk/weather.ts b/examples/ai-sdk/weather.ts
index 35b60a8..0ef7ae4 100644
--- a/examples/ai-sdk/weather.ts
+++ b/examples/ai-sdk/weather.ts
@@ -15,7 +15,7 @@ async function main() {
tools: createAISDKTools(weather),
toolChoice: 'required',
temperature: 0,
- system: 'You are a weather assistant. Be as concise as possible.',
+ system: 'You are a helpful assistant. Be as concise as possible.',
prompt: 'What is the weather in San Francisco?'
})
diff --git a/examples/dexter/weather.ts b/examples/dexter/weather.ts
index 78ac72d..511ee30 100644
--- a/examples/dexter/weather.ts
+++ b/examples/dexter/weather.ts
@@ -12,7 +12,7 @@ async function main() {
const runner = createAIRunner({
chatModel: new ChatModel({ params: { model: 'gpt-4o', temperature: 0 } }),
functions: createDexterFunctions(weather),
- systemMessage: 'You are a weather assistant. Be as concise as possible.'
+ systemMessage: 'You are a helpful assistant. Be as concise as possible.'
})
const result = await runner('What is the weather in San Francisco?')
diff --git a/examples/genkit/weather.ts b/examples/genkit/weather.ts
index 6371592..7f6557f 100644
--- a/examples/genkit/weather.ts
+++ b/examples/genkit/weather.ts
@@ -23,7 +23,7 @@ async function main() {
role: 'system',
content: [
{
- text: 'You are a weather assistant. Be as concise as possible.'
+ text: 'You are a helpful assistant. Be as concise as possible.'
}
]
}
diff --git a/examples/langchain/weather.ts b/examples/langchain/weather.ts
index 7508173..112c90a 100644
--- a/examples/langchain/weather.ts
+++ b/examples/langchain/weather.ts
@@ -16,7 +16,7 @@ async function main() {
llm: new ChatOpenAI({ model: 'gpt-4o', temperature: 0 }),
tools,
prompt: ChatPromptTemplate.fromMessages([
- ['system', 'You are a weather assistant. Be as concise as possible.'],
+ ['system', 'You are a helpful assistant. Be as concise as possible.'],
['placeholder', '{chat_history}'],
['human', '{input}'],
['placeholder', '{agent_scratchpad}']
diff --git a/examples/openai/weather.ts b/examples/openai/weather.ts
new file mode 100644
index 0000000..39ac02d
--- /dev/null
+++ b/examples/openai/weather.ts
@@ -0,0 +1,57 @@
+#!/usr/bin/env node
+import 'dotenv/config'
+
+import OpenAI from 'openai'
+import { default as assert } from 'tiny-invariant'
+
+import { WeatherClient } from '../../src/index.js'
+
+async function main() {
+ const weather = new WeatherClient()
+ const openai = new OpenAI()
+
+ const messages: OpenAI.ChatCompletionMessageParam[] = [
+ {
+ role: 'system',
+ content: 'You are a helpful assistant. Be as concise as possible.'
+ },
+ { role: 'user', content: 'What is the weather in San Francisco?' }
+ ]
+
+ const res0 = await openai.chat.completions.create({
+ messages,
+ model: 'gpt-4o',
+ temperature: 0,
+ tools: weather.tools.specs,
+ tool_choice: 'required'
+ })
+ const message0 = res0.choices[0]?.message!
+ console.log(JSON.stringify(message0, null, 2))
+ assert(message0.role === 'assistant')
+ assert(message0.tool_calls?.[0]?.function?.name === 'get_current_weather')
+
+ const getCurrentWeather = weather.tools.get('get_current_weather')!.function
+ assert(getCurrentWeather)
+
+ const toolParams = message0.tool_calls[0].function.arguments
+ assert(typeof toolParams === 'string')
+ const toolResult = await getCurrentWeather(toolParams)
+
+ messages.push(message0)
+ messages.push({
+ role: 'tool',
+ tool_call_id: message0.tool_calls[0].id,
+ content: JSON.stringify(toolResult)
+ })
+
+ const res1 = await openai.chat.completions.create({
+ messages,
+ model: 'gpt-4o',
+ temperature: 0,
+ tools: weather.tools.specs
+ })
+ const message1 = res1.choices[0].message
+ console.log(JSON.stringify(message1, null, 2))
+}
+
+await main()
diff --git a/examples/package.json b/examples/package.json
index 89b28cf..5e90477 100644
--- a/examples/package.json
+++ b/examples/package.json
@@ -28,12 +28,14 @@
"@dexaai/dexter": "^2.0.3",
"@genkit-ai/ai": "^0.5.2",
"@genkit-ai/core": "^0.5.2",
+ "@instructor-ai/instructor": "^1.3.0",
"@langchain/core": "^0.2.5",
"@langchain/openai": "^0.1.1",
"ai": "^3.1.22",
"dotenv": "^16.4.5",
"genkitx-openai": "^0.9.0",
"langchain": "^0.2.4",
+ "openai": "^4.47.3",
"zod": "^3.23.3"
}
}
diff --git a/package.json b/package.json
index 5c38bb5..ba061f3 100644
--- a/package.json
+++ b/package.json
@@ -72,11 +72,12 @@
},
"devDependencies": {
"@dexaai/dexter": "^2.0.3",
- "@fisch0920/eslint-config": "^1.3.1",
+ "@fisch0920/eslint-config": "^1.3.3",
"@genkit-ai/ai": "^0.5.2",
+ "@instructor-ai/instructor": "^1.3.0",
"@langchain/core": "^0.2.5",
"@total-typescript/ts-reset": "^0.5.1",
- "@types/node": "^20.12.7",
+ "@types/node": "^20.13.0",
"ai": "^3.1.22",
"del-cli": "^5.1.0",
"dotenv": "^16.4.5",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index f199db3..5f1eacd 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -46,11 +46,14 @@ importers:
specifier: ^2.0.3
version: 2.1.0
'@fisch0920/eslint-config':
- specifier: ^1.3.1
- version: 1.3.2(eslint@8.57.0)(typescript@5.4.5)
+ specifier: ^1.3.3
+ version: 1.3.3(eslint@8.57.0)(typescript@5.4.5)
'@genkit-ai/ai':
specifier: ^0.5.2
version: 0.5.2
+ '@instructor-ai/instructor':
+ specifier: ^1.3.0
+ version: 1.3.0(openai@4.47.3)(zod@3.23.8)
'@langchain/core':
specifier: ^0.2.5
version: 0.2.5(langchain@0.2.4(openai@4.47.3))(openai@4.47.3)
@@ -58,7 +61,7 @@ importers:
specifier: ^0.5.1
version: 0.5.1
'@types/node':
- specifier: ^20.12.7
+ specifier: ^20.13.0
version: 20.13.0
ai:
specifier: ^3.1.22
@@ -126,6 +129,9 @@ importers:
'@genkit-ai/core':
specifier: ^0.5.2
version: 0.5.2
+ '@instructor-ai/instructor':
+ specifier: ^1.3.0
+ version: 1.3.0(openai@4.47.3)(zod@3.23.8)
'@langchain/core':
specifier: ^0.2.5
version: 0.2.5(langchain@0.2.4(axios@1.7.2)(ignore@5.3.1)(openai@4.47.3))(openai@4.47.3)
@@ -144,6 +150,9 @@ importers:
langchain:
specifier: ^0.2.4
version: 0.2.4(axios@1.7.2)(ignore@5.3.1)(openai@4.47.3)
+ openai:
+ specifier: ^4.47.3
+ version: 4.47.3
zod:
specifier: ^3.23.3
version: 3.23.8
@@ -369,8 +378,8 @@ packages:
'@fastify/deepmerge@1.3.0':
resolution: {integrity: sha512-J8TOSBq3SoZbDhM9+R/u77hP93gz/rajSA+K2kGyijPpORPWUXHUpTaleoj+92As0S9uPRP7Oi8IqMf0u+ro6A==}
- '@fisch0920/eslint-config@1.3.2':
- resolution: {integrity: sha512-CUpMxCPWzoxvWFlmvH0OthooRlenqrezrVVleKEZv+NbibwgT4phyZadBLYsF8aB7Et2OoEzk4LKg8Xsdu5spA==}
+ '@fisch0920/eslint-config@1.3.3':
+ resolution: {integrity: sha512-BhjKXkVVSmdj1M60rAbJMaM1yFUFMlOeaWNmxOL4SNgLF2TR+LFNlcUkVH7bb2A5sq4BEc+2POBCCDXwKOlbUg==}
engines: {node: '>=18'}
peerDependencies:
typescript: ^5.0.0
@@ -405,6 +414,12 @@ packages:
resolution: {integrity: sha512-ErXXzENMH5pJt5/ssXV0DfWUZqly8nGzf0UcBV9xTnP+KyffE2mqyxIMBrZ8ijQck2nU0TQm40EQB53YreyWHw==}
engines: {node: '>=18'}
+ '@instructor-ai/instructor@1.3.0':
+ resolution: {integrity: sha512-nzadwGSkiVLcK3NAVeinPUrA6KwV5mkyWDGTXLMR8eXKbzlUwmLwQ+PTabPn2hCR+LtQ+7MvtuoR2acSTXgy6Q==}
+ peerDependencies:
+ openai: '>=4.28.0'
+ zod: '>=3.22.4'
+
'@isaacs/cliui@8.0.2':
resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
engines: {node: '>=12'}
@@ -1265,8 +1280,8 @@ packages:
resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==}
engines: {node: '>=14.16'}
- caniuse-lite@1.0.30001625:
- resolution: {integrity: sha512-4KE9N2gcRH+HQhpeiRZXd+1niLB/XNLAhSy4z7fI8EzcbcPoAqjNInxVHTiTwWfTIV4w096XG8OtCOCQQKPv3w==}
+ caniuse-lite@1.0.30001626:
+ resolution: {integrity: sha512-JRW7kAH8PFJzoPCJhLSHgDgKg5348hsQ68aqb+slnzuB5QFERv846oA/mRChmlLAOdEDeOkRn3ynb1gSFnjt3w==}
chai@5.1.1:
resolution: {integrity: sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==}
@@ -3508,6 +3523,9 @@ packages:
resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==}
engines: {node: '>=10'}
+ ramda@0.29.1:
+ resolution: {integrity: sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==}
+
range-parser@1.2.1:
resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==}
engines: {node: '>= 0.6'}
@@ -3719,6 +3737,11 @@ packages:
safer-buffer@2.1.2:
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
+ schema-stream@3.1.0:
+ resolution: {integrity: sha512-R4PoSFJnMORRGJ5i5BTHRO2Ed3Lf2h8DMofHd5XBU4ZE0lEBCTGRqOXBurjTEO2QntPSYAhv93jLt8PFMqDEPw==}
+ peerDependencies:
+ zod: 3.22.4
+
scoped-regex@3.0.0:
resolution: {integrity: sha512-yEsN6TuxZhZ1Tl9iB81frTNS292m0I/IG7+w8lTvfcJQP2x3vnpOoevjBoE3Np5A6KnZM2+RtVenihj9t6NiYg==}
engines: {node: '>=12'}
@@ -4458,6 +4481,12 @@ packages:
resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==}
engines: {node: '>=12.20'}
+ zod-stream@1.0.3:
+ resolution: {integrity: sha512-HxK/PZ0faOMgI1Pgjhcwin22StvlwiaYo6R7jWCT3jOFcPa4wGyFLVpeC5TwmpT6YlZhNJfDoB0qJoa+rQLYmQ==}
+ peerDependencies:
+ openai: '>=4.24.1'
+ zod: '>=3.22.4'
+
zod-to-json-schema@3.22.5:
resolution: {integrity: sha512-+akaPo6a0zpVCCseDed504KBJUQpEW5QZw7RMneNmKw+fGaML1Z9tUNLnHHAC8x6dzVRO1eB2oEMyZRnuBZg7Q==}
peerDependencies:
@@ -4468,6 +4497,12 @@ packages:
peerDependencies:
zod: ^3.23.3
+ zod-validation-error@2.1.0:
+ resolution: {integrity: sha512-VJh93e2wb4c3tWtGgTa0OF/dTt/zoPCPzXq4V11ZjxmEAFaPi/Zss1xIZdEB5RD8GD00U0/iVXgqkF77RV7pdQ==}
+ engines: {node: '>=18.0.0'}
+ peerDependencies:
+ zod: ^3.18.0
+
zod-validation-error@3.3.0:
resolution: {integrity: sha512-Syib9oumw1NTqEv4LT0e6U83Td9aVRk9iTXPUQr1otyV1PuXQKOvOwhMNqZIq5hluzHP2pMgnOmHEo7kPdI2mw==}
engines: {node: '>=18.0.0'}
@@ -4650,7 +4685,7 @@ snapshots:
'@fastify/deepmerge@1.3.0': {}
- '@fisch0920/eslint-config@1.3.2(eslint@8.57.0)(typescript@5.4.5)':
+ '@fisch0920/eslint-config@1.3.3(eslint@8.57.0)(typescript@5.4.5)':
dependencies:
'@rushstack/eslint-patch': 1.10.3
'@typescript-eslint/eslint-plugin': 7.11.0(@typescript-eslint/parser@7.11.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5)
@@ -4731,6 +4766,13 @@ snapshots:
'@inquirer/figures@1.0.3': {}
+ '@instructor-ai/instructor@1.3.0(openai@4.47.3)(zod@3.23.8)':
+ dependencies:
+ openai: 4.47.3
+ zod: 3.23.8
+ zod-stream: 1.0.3(openai@4.47.3)(zod@3.23.8)
+ zod-validation-error: 2.1.0(zod@3.23.8)
+
'@isaacs/cliui@8.0.2':
dependencies:
string-width: 5.1.2
@@ -5666,7 +5708,7 @@ snapshots:
browserslist@4.23.0:
dependencies:
- caniuse-lite: 1.0.30001625
+ caniuse-lite: 1.0.30001626
electron-to-chromium: 1.4.788
node-releases: 2.0.14
update-browserslist-db: 1.0.16(browserslist@4.23.0)
@@ -5724,7 +5766,7 @@ snapshots:
camelcase@7.0.1: {}
- caniuse-lite@1.0.30001625: {}
+ caniuse-lite@1.0.30001626: {}
chai@5.1.1:
dependencies:
@@ -8041,6 +8083,8 @@ snapshots:
quick-lru@5.1.1: {}
+ ramda@0.29.1: {}
+
range-parser@1.2.1: {}
raw-body@2.5.2:
@@ -8291,6 +8335,11 @@ snapshots:
safer-buffer@2.1.2: {}
+ schema-stream@3.1.0(zod@3.23.8):
+ dependencies:
+ ramda: 0.29.1
+ zod: 3.23.8
+
scoped-regex@3.0.0: {}
secure-json-parse@2.7.0: {}
@@ -9070,6 +9119,13 @@ snapshots:
yocto-queue@1.0.0: {}
+ zod-stream@1.0.3(openai@4.47.3)(zod@3.23.8):
+ dependencies:
+ openai: 4.47.3
+ schema-stream: 3.1.0(zod@3.23.8)
+ zod: 3.23.8
+ zod-to-json-schema: 3.23.0(zod@3.23.8)
+
zod-to-json-schema@3.22.5(zod@3.23.8):
dependencies:
zod: 3.23.8
@@ -9078,6 +9134,10 @@ snapshots:
dependencies:
zod: 3.23.8
+ zod-validation-error@2.1.0(zod@3.23.8):
+ dependencies:
+ zod: 3.23.8
+
zod-validation-error@3.3.0(zod@3.23.8):
dependencies:
zod: 3.23.8
diff --git a/readme.md b/readme.md
index 97655a4..6732ff2 100644
--- a/readme.md
+++ b/readme.md
@@ -13,7 +13,7 @@