@lobehub/chat 1.138.3 → 1.138.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +50 -0
- package/changelog/v1.json +18 -0
- package/package.json +1 -1
- package/packages/database/src/repositories/aiInfra/index.test.ts +656 -0
- package/packages/model-runtime/src/core/contextBuilders/google.test.ts +585 -0
- package/packages/model-runtime/src/core/contextBuilders/google.ts +201 -0
- package/packages/model-runtime/src/core/openaiCompatibleFactory/index.test.ts +191 -179
- package/packages/model-runtime/src/core/openaiCompatibleFactory/index.ts +305 -47
- package/packages/model-runtime/src/providers/anthropic/generateObject.test.ts +93 -84
- package/packages/model-runtime/src/providers/anthropic/generateObject.ts +3 -3
- package/packages/model-runtime/src/providers/google/generateObject.test.ts +588 -83
- package/packages/model-runtime/src/providers/google/generateObject.ts +104 -6
- package/packages/model-runtime/src/providers/google/index.test.ts +0 -395
- package/packages/model-runtime/src/providers/google/index.ts +28 -194
- package/packages/model-runtime/src/providers/openai/index.test.ts +18 -17
- package/packages/model-runtime/src/types/structureOutput.ts +3 -4
- package/packages/types/src/aiChat.ts +0 -1
- package/src/app/(backend)/trpc/edge/[trpc]/route.ts +0 -2
- package/src/server/routers/edge/index.ts +2 -1
- package/src/server/routers/lambda/aiChat.ts +1 -2
- package/src/server/routers/lambda/index.ts +2 -0
- package/src/server/routers/lambda/upload.ts +16 -0
- package/src/services/__tests__/upload.test.ts +266 -18
- package/src/services/upload.ts +2 -2
|
@@ -28,9 +28,9 @@ describe('Anthropic generateObject', () => {
|
|
|
28
28
|
create: vi.fn().mockResolvedValue({
|
|
29
29
|
content: [
|
|
30
30
|
{
|
|
31
|
-
|
|
31
|
+
input: { age: 30, name: 'John' },
|
|
32
32
|
name: 'person_extractor',
|
|
33
|
-
|
|
33
|
+
type: 'tool_use',
|
|
34
34
|
},
|
|
35
35
|
],
|
|
36
36
|
}),
|
|
@@ -39,48 +39,48 @@ describe('Anthropic generateObject', () => {
|
|
|
39
39
|
|
|
40
40
|
const payload = {
|
|
41
41
|
messages: [{ content: 'Generate a person object', role: 'user' as const }],
|
|
42
|
+
model: 'claude-3-5-sonnet-20241022',
|
|
42
43
|
schema: {
|
|
43
|
-
name: 'person_extractor',
|
|
44
44
|
description: 'Extract person information',
|
|
45
|
+
name: 'person_extractor',
|
|
45
46
|
schema: {
|
|
46
|
-
type: '
|
|
47
|
-
properties: { name: { type: 'string' }, age: { type: 'number' } },
|
|
47
|
+
properties: { age: { type: 'number' }, name: { type: 'string' } },
|
|
48
48
|
required: ['name', 'age'],
|
|
49
|
+
type: 'object' as const,
|
|
49
50
|
},
|
|
50
51
|
},
|
|
51
|
-
model: 'claude-3-5-sonnet-20241022',
|
|
52
52
|
};
|
|
53
53
|
|
|
54
54
|
const result = await createAnthropicGenerateObject(mockClient as any, payload);
|
|
55
55
|
|
|
56
56
|
expect(mockClient.messages.create).toHaveBeenCalledWith(
|
|
57
57
|
expect.objectContaining({
|
|
58
|
-
model: 'claude-3-5-sonnet-20241022',
|
|
59
58
|
max_tokens: 8192,
|
|
60
59
|
messages: [{ content: 'Generate a person object', role: 'user' }],
|
|
60
|
+
model: 'claude-3-5-sonnet-20241022',
|
|
61
|
+
tool_choice: {
|
|
62
|
+
name: 'person_extractor',
|
|
63
|
+
type: 'tool',
|
|
64
|
+
},
|
|
61
65
|
tools: [
|
|
62
66
|
{
|
|
63
|
-
name: 'person_extractor',
|
|
64
67
|
description: 'Extract person information',
|
|
65
68
|
input_schema: {
|
|
66
|
-
type: 'object',
|
|
67
69
|
properties: {
|
|
68
|
-
name: { type: 'string' },
|
|
69
70
|
age: { type: 'number' },
|
|
71
|
+
name: { type: 'string' },
|
|
70
72
|
},
|
|
71
73
|
required: ['name', 'age'],
|
|
74
|
+
type: 'object',
|
|
72
75
|
},
|
|
76
|
+
name: 'person_extractor',
|
|
73
77
|
},
|
|
74
78
|
],
|
|
75
|
-
tool_choice: {
|
|
76
|
-
type: 'tool',
|
|
77
|
-
name: 'person_extractor',
|
|
78
|
-
},
|
|
79
79
|
}),
|
|
80
80
|
expect.objectContaining({}),
|
|
81
81
|
);
|
|
82
82
|
|
|
83
|
-
expect(result).toEqual({ name: 'John'
|
|
83
|
+
expect(result).toEqual({ age: 30, name: 'John' });
|
|
84
84
|
});
|
|
85
85
|
|
|
86
86
|
it('should handle system messages correctly', async () => {
|
|
@@ -89,9 +89,9 @@ describe('Anthropic generateObject', () => {
|
|
|
89
89
|
create: vi.fn().mockResolvedValue({
|
|
90
90
|
content: [
|
|
91
91
|
{
|
|
92
|
-
type: 'tool_use',
|
|
93
|
-
name: 'status_extractor',
|
|
94
92
|
input: { status: 'success' },
|
|
93
|
+
name: 'status_extractor',
|
|
94
|
+
type: 'tool_use',
|
|
95
95
|
},
|
|
96
96
|
],
|
|
97
97
|
}),
|
|
@@ -103,19 +103,19 @@ describe('Anthropic generateObject', () => {
|
|
|
103
103
|
{ content: 'You are a helpful assistant', role: 'system' as const },
|
|
104
104
|
{ content: 'Generate status', role: 'user' as const },
|
|
105
105
|
],
|
|
106
|
+
model: 'claude-3-5-sonnet-20241022',
|
|
106
107
|
schema: {
|
|
107
108
|
name: 'status_extractor',
|
|
108
|
-
schema: {
|
|
109
|
+
schema: { properties: { status: { type: 'string' } }, type: 'object' as const },
|
|
109
110
|
},
|
|
110
|
-
model: 'claude-3-5-sonnet-20241022',
|
|
111
111
|
};
|
|
112
112
|
|
|
113
113
|
const result = await createAnthropicGenerateObject(mockClient as any, payload);
|
|
114
114
|
|
|
115
115
|
expect(mockClient.messages.create).toHaveBeenCalledWith(
|
|
116
116
|
expect.objectContaining({
|
|
117
|
-
system: [{ text: 'You are a helpful assistant', type: 'text' }],
|
|
118
117
|
messages: expect.any(Array),
|
|
118
|
+
system: [{ text: 'You are a helpful assistant', type: 'text' }],
|
|
119
119
|
}),
|
|
120
120
|
expect.any(Object),
|
|
121
121
|
);
|
|
@@ -129,9 +129,9 @@ describe('Anthropic generateObject', () => {
|
|
|
129
129
|
create: vi.fn().mockResolvedValue({
|
|
130
130
|
content: [
|
|
131
131
|
{
|
|
132
|
-
type: 'tool_use',
|
|
133
|
-
name: 'data_extractor',
|
|
134
132
|
input: { data: 'test' },
|
|
133
|
+
name: 'data_extractor',
|
|
134
|
+
type: 'tool_use',
|
|
135
135
|
},
|
|
136
136
|
],
|
|
137
137
|
}),
|
|
@@ -140,11 +140,11 @@ describe('Anthropic generateObject', () => {
|
|
|
140
140
|
|
|
141
141
|
const payload = {
|
|
142
142
|
messages: [{ content: 'Generate data', role: 'user' as const }],
|
|
143
|
+
model: 'claude-3-5-sonnet-20241022',
|
|
143
144
|
schema: {
|
|
144
145
|
name: 'data_extractor',
|
|
145
|
-
schema: {
|
|
146
|
+
schema: { properties: { data: { type: 'string' } }, type: 'object' as const },
|
|
146
147
|
},
|
|
147
|
-
model: 'claude-3-5-sonnet-20241022',
|
|
148
148
|
};
|
|
149
149
|
|
|
150
150
|
const options = {
|
|
@@ -169,8 +169,8 @@ describe('Anthropic generateObject', () => {
|
|
|
169
169
|
create: vi.fn().mockResolvedValue({
|
|
170
170
|
content: [
|
|
171
171
|
{
|
|
172
|
-
type: 'text',
|
|
173
172
|
text: 'Some text response without tool use',
|
|
173
|
+
type: 'text',
|
|
174
174
|
},
|
|
175
175
|
],
|
|
176
176
|
}),
|
|
@@ -179,11 +179,11 @@ describe('Anthropic generateObject', () => {
|
|
|
179
179
|
|
|
180
180
|
const payload = {
|
|
181
181
|
messages: [{ content: 'Generate data', role: 'user' as const }],
|
|
182
|
+
model: 'claude-3-5-sonnet-20241022',
|
|
182
183
|
schema: {
|
|
183
184
|
name: 'test_tool',
|
|
184
185
|
schema: { type: 'object' },
|
|
185
186
|
},
|
|
186
|
-
model: 'claude-3-5-sonnet-20241022',
|
|
187
187
|
};
|
|
188
188
|
|
|
189
189
|
const result = await createAnthropicGenerateObject(mockClient as any, payload as any);
|
|
@@ -197,9 +197,10 @@ describe('Anthropic generateObject', () => {
|
|
|
197
197
|
create: vi.fn().mockResolvedValue({
|
|
198
198
|
content: [
|
|
199
199
|
{
|
|
200
|
-
type: 'tool_use',
|
|
201
|
-
name: 'user_extractor',
|
|
202
200
|
input: {
|
|
201
|
+
metadata: {
|
|
202
|
+
created: '2024-01-01',
|
|
203
|
+
},
|
|
203
204
|
user: {
|
|
204
205
|
name: 'Alice',
|
|
205
206
|
profile: {
|
|
@@ -207,10 +208,9 @@ describe('Anthropic generateObject', () => {
|
|
|
207
208
|
preferences: ['music', 'sports'],
|
|
208
209
|
},
|
|
209
210
|
},
|
|
210
|
-
metadata: {
|
|
211
|
-
created: '2024-01-01',
|
|
212
|
-
},
|
|
213
211
|
},
|
|
212
|
+
name: 'user_extractor',
|
|
213
|
+
type: 'tool_use',
|
|
214
214
|
},
|
|
215
215
|
],
|
|
216
216
|
}),
|
|
@@ -219,35 +219,38 @@ describe('Anthropic generateObject', () => {
|
|
|
219
219
|
|
|
220
220
|
const payload = {
|
|
221
221
|
messages: [{ content: 'Generate complex user data', role: 'user' as const }],
|
|
222
|
+
model: 'claude-3-5-sonnet-20241022',
|
|
222
223
|
schema: {
|
|
223
|
-
name: 'user_extractor',
|
|
224
224
|
description: 'Extract complex user information',
|
|
225
|
+
name: 'user_extractor',
|
|
225
226
|
schema: {
|
|
226
|
-
type: 'object' as const,
|
|
227
227
|
properties: {
|
|
228
|
+
metadata: { type: 'object' },
|
|
228
229
|
user: {
|
|
229
|
-
type: 'object',
|
|
230
230
|
properties: {
|
|
231
231
|
name: { type: 'string' },
|
|
232
232
|
profile: {
|
|
233
|
-
type: 'object',
|
|
234
233
|
properties: {
|
|
235
234
|
age: { type: 'number' },
|
|
236
|
-
preferences: {
|
|
235
|
+
preferences: { items: { type: 'string' }, type: 'array' },
|
|
237
236
|
},
|
|
237
|
+
type: 'object',
|
|
238
238
|
},
|
|
239
239
|
},
|
|
240
|
+
type: 'object',
|
|
240
241
|
},
|
|
241
|
-
metadata: { type: 'object' },
|
|
242
242
|
},
|
|
243
|
+
type: 'object' as const,
|
|
243
244
|
},
|
|
244
245
|
},
|
|
245
|
-
model: 'claude-3-5-sonnet-20241022',
|
|
246
246
|
};
|
|
247
247
|
|
|
248
248
|
const result = await createAnthropicGenerateObject(mockClient as any, payload);
|
|
249
249
|
|
|
250
250
|
expect(result).toEqual({
|
|
251
|
+
metadata: {
|
|
252
|
+
created: '2024-01-01',
|
|
253
|
+
},
|
|
251
254
|
user: {
|
|
252
255
|
name: 'Alice',
|
|
253
256
|
profile: {
|
|
@@ -255,9 +258,6 @@ describe('Anthropic generateObject', () => {
|
|
|
255
258
|
preferences: ['music', 'sports'],
|
|
256
259
|
},
|
|
257
260
|
},
|
|
258
|
-
metadata: {
|
|
259
|
-
created: '2024-01-01',
|
|
260
|
-
},
|
|
261
261
|
});
|
|
262
262
|
});
|
|
263
263
|
});
|
|
@@ -269,14 +269,14 @@ describe('Anthropic generateObject', () => {
|
|
|
269
269
|
create: vi.fn().mockResolvedValue({
|
|
270
270
|
content: [
|
|
271
271
|
{
|
|
272
|
-
type: 'tool_use',
|
|
273
|
-
name: 'get_weather',
|
|
274
272
|
input: { city: 'New York', unit: 'celsius' },
|
|
273
|
+
name: 'get_weather',
|
|
274
|
+
type: 'tool_use',
|
|
275
275
|
},
|
|
276
276
|
{
|
|
277
|
-
type: 'tool_use',
|
|
278
|
-
name: 'get_time',
|
|
279
277
|
input: { timezone: 'America/New_York' },
|
|
278
|
+
name: 'get_time',
|
|
279
|
+
type: 'tool_use',
|
|
280
280
|
},
|
|
281
281
|
],
|
|
282
282
|
}),
|
|
@@ -285,69 +285,75 @@ describe('Anthropic generateObject', () => {
|
|
|
285
285
|
|
|
286
286
|
const payload = {
|
|
287
287
|
messages: [{ content: 'What is the weather and time in New York?', role: 'user' as const }],
|
|
288
|
+
model: 'claude-3-5-sonnet-20241022',
|
|
288
289
|
tools: [
|
|
289
290
|
{
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
291
|
+
function: {
|
|
292
|
+
description: 'Get weather information',
|
|
293
|
+
name: 'get_weather',
|
|
294
|
+
parameters: {
|
|
295
|
+
properties: {
|
|
296
|
+
city: { type: 'string' },
|
|
297
|
+
unit: { type: 'string' },
|
|
298
|
+
},
|
|
299
|
+
required: ['city'],
|
|
300
|
+
type: 'object' as const,
|
|
297
301
|
},
|
|
298
|
-
required: ['city'],
|
|
299
302
|
},
|
|
303
|
+
type: 'function' as const,
|
|
300
304
|
},
|
|
301
305
|
{
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
306
|
+
function: {
|
|
307
|
+
description: 'Get current time',
|
|
308
|
+
name: 'get_time',
|
|
309
|
+
parameters: {
|
|
310
|
+
properties: {
|
|
311
|
+
timezone: { type: 'string' },
|
|
312
|
+
},
|
|
313
|
+
required: ['timezone'],
|
|
314
|
+
type: 'object' as const,
|
|
308
315
|
},
|
|
309
|
-
required: ['timezone'],
|
|
310
316
|
},
|
|
317
|
+
type: 'function' as const,
|
|
311
318
|
},
|
|
312
319
|
],
|
|
313
|
-
model: 'claude-3-5-sonnet-20241022',
|
|
314
320
|
};
|
|
315
321
|
|
|
316
322
|
const result = await createAnthropicGenerateObject(mockClient as any, payload as any);
|
|
317
323
|
|
|
318
324
|
expect(mockClient.messages.create).toHaveBeenCalledWith(
|
|
319
325
|
expect.objectContaining({
|
|
320
|
-
model: 'claude-3-5-sonnet-20241022',
|
|
321
326
|
max_tokens: 8192,
|
|
322
327
|
messages: [{ content: 'What is the weather and time in New York?', role: 'user' }],
|
|
328
|
+
model: 'claude-3-5-sonnet-20241022',
|
|
329
|
+
tool_choice: {
|
|
330
|
+
type: 'any',
|
|
331
|
+
},
|
|
323
332
|
tools: [
|
|
324
333
|
{
|
|
325
|
-
name: 'get_weather',
|
|
326
334
|
description: 'Get weather information',
|
|
327
335
|
input_schema: {
|
|
328
|
-
type: 'object',
|
|
329
336
|
properties: {
|
|
330
337
|
city: { type: 'string' },
|
|
331
338
|
unit: { type: 'string' },
|
|
332
339
|
},
|
|
333
340
|
required: ['city'],
|
|
341
|
+
type: 'object',
|
|
334
342
|
},
|
|
343
|
+
name: 'get_weather',
|
|
335
344
|
},
|
|
336
345
|
{
|
|
337
|
-
name: 'get_time',
|
|
338
346
|
description: 'Get current time',
|
|
339
347
|
input_schema: {
|
|
340
|
-
type: 'object',
|
|
341
348
|
properties: {
|
|
342
349
|
timezone: { type: 'string' },
|
|
343
350
|
},
|
|
344
351
|
required: ['timezone'],
|
|
352
|
+
type: 'object',
|
|
345
353
|
},
|
|
354
|
+
name: 'get_time',
|
|
346
355
|
},
|
|
347
356
|
],
|
|
348
|
-
tool_choice: {
|
|
349
|
-
type: 'any',
|
|
350
|
-
},
|
|
351
357
|
}),
|
|
352
358
|
expect.objectContaining({}),
|
|
353
359
|
);
|
|
@@ -364,9 +370,9 @@ describe('Anthropic generateObject', () => {
|
|
|
364
370
|
create: vi.fn().mockResolvedValue({
|
|
365
371
|
content: [
|
|
366
372
|
{
|
|
367
|
-
|
|
373
|
+
input: { a: 5, b: 3, operation: 'add' },
|
|
368
374
|
name: 'calculate',
|
|
369
|
-
|
|
375
|
+
type: 'tool_use',
|
|
370
376
|
},
|
|
371
377
|
],
|
|
372
378
|
}),
|
|
@@ -375,27 +381,30 @@ describe('Anthropic generateObject', () => {
|
|
|
375
381
|
|
|
376
382
|
const payload = {
|
|
377
383
|
messages: [{ content: 'Add 5 and 3', role: 'user' as const }],
|
|
384
|
+
model: 'claude-3-5-sonnet-20241022',
|
|
378
385
|
tools: [
|
|
379
386
|
{
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
387
|
+
function: {
|
|
388
|
+
description: 'Perform mathematical calculation',
|
|
389
|
+
name: 'calculate',
|
|
390
|
+
parameters: {
|
|
391
|
+
properties: {
|
|
392
|
+
a: { type: 'number' },
|
|
393
|
+
b: { type: 'number' },
|
|
394
|
+
operation: { type: 'string' },
|
|
395
|
+
},
|
|
396
|
+
required: ['operation', 'a', 'b'],
|
|
397
|
+
type: 'object' as const,
|
|
388
398
|
},
|
|
389
|
-
required: ['operation', 'a', 'b'],
|
|
390
399
|
},
|
|
400
|
+
type: 'function' as const,
|
|
391
401
|
},
|
|
392
402
|
],
|
|
393
|
-
model: 'claude-3-5-sonnet-20241022',
|
|
394
403
|
};
|
|
395
404
|
|
|
396
405
|
const result = await createAnthropicGenerateObject(mockClient as any, payload as any);
|
|
397
406
|
|
|
398
|
-
expect(result).toEqual([{ arguments: {
|
|
407
|
+
expect(result).toEqual([{ arguments: { a: 5, b: 3, operation: 'add' }, name: 'calculate' }]);
|
|
399
408
|
});
|
|
400
409
|
});
|
|
401
410
|
|
|
@@ -410,11 +419,11 @@ describe('Anthropic generateObject', () => {
|
|
|
410
419
|
|
|
411
420
|
const payload = {
|
|
412
421
|
messages: [{ content: 'Generate data', role: 'user' as const }],
|
|
422
|
+
model: 'claude-3-5-sonnet-20241022',
|
|
413
423
|
schema: {
|
|
414
424
|
name: 'test_tool',
|
|
415
425
|
schema: { type: 'object' },
|
|
416
426
|
},
|
|
417
|
-
model: 'claude-3-5-sonnet-20241022',
|
|
418
427
|
};
|
|
419
428
|
|
|
420
429
|
await expect(createAnthropicGenerateObject(mockClient as any, payload as any)).rejects.toThrow(
|
|
@@ -434,11 +443,11 @@ describe('Anthropic generateObject', () => {
|
|
|
434
443
|
|
|
435
444
|
const payload = {
|
|
436
445
|
messages: [{ content: 'Generate data', role: 'user' as const }],
|
|
446
|
+
model: 'claude-3-5-sonnet-20241022',
|
|
437
447
|
schema: {
|
|
438
448
|
name: 'test_tool',
|
|
439
449
|
schema: { type: 'object' },
|
|
440
450
|
},
|
|
441
|
-
model: 'claude-3-5-sonnet-20241022',
|
|
442
451
|
};
|
|
443
452
|
|
|
444
453
|
const options = {
|
|
@@ -14,14 +14,14 @@ export const createAnthropicGenerateObject = async (
|
|
|
14
14
|
payload: GenerateObjectPayload,
|
|
15
15
|
options?: GenerateObjectOptions,
|
|
16
16
|
) => {
|
|
17
|
-
const { schema, messages,
|
|
17
|
+
const { schema, messages, model, tools } = payload;
|
|
18
18
|
|
|
19
19
|
log('generateObject called with model: %s', model);
|
|
20
20
|
log('schema: %O', schema);
|
|
21
21
|
log('messages count: %d', messages.length);
|
|
22
22
|
|
|
23
23
|
// Convert messages to Anthropic format
|
|
24
|
-
const system_message =
|
|
24
|
+
const system_message = messages.find((m) => m.role === 'system')?.content;
|
|
25
25
|
const user_messages = messages.filter((m) => m.role !== 'system');
|
|
26
26
|
const anthropicMessages = await buildAnthropicMessages(user_messages);
|
|
27
27
|
|
|
@@ -39,7 +39,7 @@ export const createAnthropicGenerateObject = async (
|
|
|
39
39
|
let finalTools;
|
|
40
40
|
let tool_choice: Anthropic.ToolChoiceAny | Anthropic.ToolChoiceTool;
|
|
41
41
|
if (tools) {
|
|
42
|
-
finalTools = buildAnthropicTools(tools
|
|
42
|
+
finalTools = buildAnthropicTools(tools);
|
|
43
43
|
tool_choice = { type: 'any' };
|
|
44
44
|
} else if (schema) {
|
|
45
45
|
// Convert OpenAI-style schema to Anthropic tool format
|