Skip to content

Commit 23024c9

Browse files
committed
feat: remove preset usage example and add new tutorials for AI agent, CRM system, federation, and task manager
1 parent d83a979 commit 23024c9

File tree

25 files changed

+468
-149
lines changed

25 files changed

+468
-149
lines changed

examples/scenarios/preset-usage/CHANGELOG.md

Lines changed: 0 additions & 55 deletions
This file was deleted.

examples/scenarios/preset-usage/README.md

Lines changed: 0 additions & 16 deletions
This file was deleted.

examples/scenarios/preset-usage/objectql.config.ts

Lines changed: 0 additions & 15 deletions
This file was deleted.

examples/scenarios/preset-usage/package.json

Lines changed: 0 additions & 31 deletions
This file was deleted.

examples/scenarios/preset-usage/src/index.ts

Lines changed: 0 additions & 23 deletions
This file was deleted.

examples/scenarios/preset-usage/tsconfig.json

Lines changed: 0 additions & 9 deletions
This file was deleted.
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
import OpenAI from "openai";
2+
import { ObjectQL } from '@objectql/core';
3+
import { KnexDriver } from '@objectql/driver-sql';
4+
import dotenv from 'dotenv';
5+
6+
dotenv.config();
7+
8+
// Tool Definitions
9+
const productTools: OpenAI.Chat.Completions.ChatCompletionTool[] = [
10+
{
11+
type: "function",
12+
function: {
13+
name: "find_products",
14+
description: "Search for products and check stock levels. Returns list of products matching the filter.",
15+
parameters: {
16+
type: "object",
17+
properties: {
18+
filters: {
19+
type: "array",
20+
description: "ObjectQL filters, e.g. [['name', 'contains', 'ipad']]",
21+
items: {
22+
type: "array"
23+
}
24+
}
25+
},
26+
required: ["filters"]
27+
}
28+
}
29+
},
30+
{
31+
type: "function",
32+
function: {
33+
name: "update_stock",
34+
description: "Update the stock quantity for a product",
35+
parameters: {
36+
type: "object",
37+
properties: {
38+
sku: { type: "string" },
39+
quantity_change: { type: "number", description: "Negative to reduce stock, positive to add" }
40+
},
41+
required: ["sku", "quantity_change"]
42+
}
43+
}
44+
}
45+
];
46+
47+
async function runAgent() {
48+
// 1. Setup ObjectQL
49+
const app = new ObjectQL({
50+
driver: new KnexDriver({
51+
client: 'sqlite3',
52+
connection: { filename: './inventory.db' },
53+
useNullAsDefault: true
54+
})
55+
});
56+
await app.init(); // Load metadata
57+
58+
// Seed some data if empty
59+
try {
60+
const existing = await app.find('product', {});
61+
if (existing.length === 0) {
62+
console.log("Seeding initial data...");
63+
await app.create('product', { name: "MacBook Pro 16", sku: "MBP16", stock_quantity: 10, price: 2499 });
64+
await app.create('product', { name: "iPad Air", sku: "IPAD-AIR", stock_quantity: 50, price: 599 });
65+
}
66+
} catch (e) {
67+
console.warn("Database init error:", e);
68+
}
69+
70+
if (!process.env.OPENAI_API_KEY) {
71+
console.error("Please set OPENAI_API_KEY in .env");
72+
return;
73+
}
74+
75+
// 2. Setup OpenAI
76+
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
77+
78+
const userQuery = process.argv[2] || "How many iPad Airs do we have?";
79+
console.log(`\nUser: "${userQuery}"`);
80+
81+
// Step 1: LLM decides what to do
82+
const completion = await openai.chat.completions.create({
83+
model: "gpt-4-turbo",
84+
messages: [{ role: "user", content: userQuery }],
85+
tools: productTools,
86+
});
87+
88+
const choice = completion.choices[0];
89+
const toolCall = choice.message.tool_calls?.[0];
90+
91+
if (toolCall) {
92+
console.log(`\nAgent decided to call tool: ${toolCall.function.name}`);
93+
const args = JSON.parse(toolCall.function.arguments);
94+
console.log(`Arguments:`, args);
95+
96+
let result;
97+
if (toolCall.function.name === 'find_products') {
98+
result = await app.find('product', args.filters || []);
99+
} else if (toolCall.function.name === 'update_stock') {
100+
const products = await app.find('product', [['sku', '=', args.sku]]);
101+
if (products.length > 0) {
102+
const product = products[0];
103+
const newQty = (product.stock_quantity || 0) + args.quantity_change;
104+
result = await app.update('product', product.id, { stock_quantity: newQty });
105+
} else {
106+
result = { error: "Product not found" };
107+
}
108+
}
109+
110+
console.log(`\nTool Output:`, JSON.stringify(result, null, 2));
111+
112+
// Step 2: Feed back to LLM (Optional simplification for tutorial)
113+
const finalResponse = await openai.chat.completions.create({
114+
model: "gpt-4-turbo",
115+
messages: [
116+
{ role: "user", content: userQuery },
117+
choice.message,
118+
{
119+
role: "tool",
120+
tool_call_id: toolCall.id,
121+
content: JSON.stringify(result)
122+
}
123+
]
124+
});
125+
126+
console.log(`\nAgent Final Answer: ${finalResponse.choices[0].message.content}`);
127+
} else {
128+
console.log(`\nAgent Answer: ${choice.message.content}`);
129+
}
130+
}
131+
132+
runAgent();
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"name": "@example/tutorial-ai-agent",
3+
"version": "1.0.0",
4+
"private": true,
5+
"scripts": {
6+
"start": "tsx agent.ts"
7+
},
8+
"dependencies": {
9+
"@objectql/core": "workspace:*",
10+
"@objectql/server": "workspace:*",
11+
"@objectql/driver-sql": "workspace:*",
12+
"sqlite3": "^5.1.7",
13+
"openai": "^4.28.0",
14+
"dotenv": "^16.4.5"
15+
},
16+
"devDependencies": {
17+
"tsx": "^4.7.1",
18+
"typescript": "^5.3.3",
19+
"@types/node": "^20.11.24"
20+
}
21+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
name: product
2+
label: Product
3+
fields:
4+
name:
5+
type: text
6+
required: true
7+
searchable: true
8+
sku:
9+
type: text
10+
required: true
11+
unique: true
12+
stock_quantity:
13+
type: number
14+
defaultValue: 0
15+
price:
16+
type: currency
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"compilerOptions": {
3+
"target": "ES2020",
4+
"module": "CommonJS",
5+
"moduleResolution": "node",
6+
"strict": true,
7+
"esModuleInterop": true,
8+
"skipLibCheck": true,
9+
"forceConsistentCasingInFileNames": true
10+
}
11+
}

0 commit comments

Comments
 (0)