cencori 1.0.3 → 1.1.0
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/README.md +28 -6
- package/dist/ai/index.d.mts +70 -1
- package/dist/ai/index.d.ts +70 -1
- package/dist/ai/index.js +125 -0
- package/dist/ai/index.js.map +1 -1
- package/dist/ai/index.mjs +125 -0
- package/dist/ai/index.mjs.map +1 -1
- package/dist/index.d.mts +24 -1
- package/dist/index.d.ts +24 -1
- package/dist/index.js +299 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +297 -0
- package/dist/index.mjs.map +1 -1
- package/dist/memory/index.d.mts +126 -0
- package/dist/memory/index.d.ts +126 -0
- package/dist/memory/index.js +161 -0
- package/dist/memory/index.js.map +1 -0
- package/dist/memory/index.mjs +135 -0
- package/dist/memory/index.mjs.map +1 -0
- package/dist/telemetry/index.d.mts +73 -0
- package/dist/telemetry/index.d.ts +73 -0
- package/dist/telemetry/index.js +68 -0
- package/dist/telemetry/index.js.map +1 -0
- package/dist/telemetry/index.mjs +43 -0
- package/dist/telemetry/index.mjs.map +1 -0
- package/package.json +7 -2
package/README.md
CHANGED
|
@@ -134,10 +134,12 @@ console.log(response.embeddings[0]); // [0.1, 0.2, ...]
|
|
|
134
134
|
|
|
135
135
|
### Image Generation
|
|
136
136
|
|
|
137
|
+
Generate images from text prompts using multiple providers:
|
|
138
|
+
|
|
137
139
|
```typescript
|
|
138
140
|
const response = await cencori.ai.generateImage({
|
|
139
141
|
prompt: 'A futuristic city at sunset with flying cars',
|
|
140
|
-
model: '
|
|
142
|
+
model: 'gpt-image-1.5', // Best text rendering, top ELO rating
|
|
141
143
|
size: '1024x1024',
|
|
142
144
|
quality: 'hd'
|
|
143
145
|
});
|
|
@@ -145,6 +147,12 @@ const response = await cencori.ai.generateImage({
|
|
|
145
147
|
console.log(response.images[0].url); // https://...
|
|
146
148
|
```
|
|
147
149
|
|
|
150
|
+
**Supported Models:**
|
|
151
|
+
| Provider | Models | Description |
|
|
152
|
+
|----------|--------|-------------|
|
|
153
|
+
| **OpenAI** | `gpt-image-1.5`, `gpt-image-1`, `dall-e-3`, `dall-e-2` | Text rendering, creative |
|
|
154
|
+
| **Google** | `gemini-3-pro-image`, `imagen-3` | High photorealism |
|
|
155
|
+
|
|
148
156
|
## Framework Integrations
|
|
149
157
|
|
|
150
158
|
### Vercel AI SDK
|
|
@@ -205,15 +213,29 @@ await cencori.workflow.trigger('data-enrichment', {
|
|
|
205
213
|
});
|
|
206
214
|
```
|
|
207
215
|
|
|
208
|
-
###
|
|
216
|
+
### Memory (Context Store)
|
|
209
217
|
|
|
210
218
|
```typescript
|
|
211
|
-
//
|
|
212
|
-
|
|
213
|
-
|
|
219
|
+
// Store a memory with auto-embedding
|
|
220
|
+
await cencori.memory.store({
|
|
221
|
+
namespace: 'docs',
|
|
222
|
+
content: 'Refund policy allows returns within 30 days',
|
|
223
|
+
metadata: { category: 'policy' }
|
|
214
224
|
});
|
|
215
225
|
|
|
216
|
-
|
|
226
|
+
// Semantic search
|
|
227
|
+
const results = await cencori.memory.search({
|
|
228
|
+
namespace: 'docs',
|
|
229
|
+
query: 'what is the refund policy?',
|
|
230
|
+
limit: 5
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
// RAG helper
|
|
234
|
+
const response = await cencori.ai.rag({
|
|
235
|
+
model: 'gpt-4o',
|
|
236
|
+
messages: [{ role: 'user', content: 'What is our refund policy?' }],
|
|
237
|
+
namespace: 'docs'
|
|
238
|
+
});
|
|
217
239
|
```
|
|
218
240
|
|
|
219
241
|
## Why Cencori?
|
package/dist/ai/index.d.mts
CHANGED
|
@@ -95,6 +95,75 @@ declare class AINamespace {
|
|
|
95
95
|
* console.log(response.images[0].url);
|
|
96
96
|
*/
|
|
97
97
|
generateImage(request: ImageGenerationRequest): Promise<ImageGenerationResponse>;
|
|
98
|
+
/**
|
|
99
|
+
* RAG (Retrieval-Augmented Generation) - Chat with automatic memory context
|
|
100
|
+
*
|
|
101
|
+
* Searches your memory namespace for relevant context and includes it
|
|
102
|
+
* in the prompt automatically. Returns the AI response along with sources.
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* const response = await cencori.ai.rag({
|
|
106
|
+
* model: 'gpt-4o',
|
|
107
|
+
* messages: [{ role: 'user', content: 'What are our company policies?' }],
|
|
108
|
+
* namespace: 'company-docs',
|
|
109
|
+
* limit: 5, // number of memories to retrieve
|
|
110
|
+
* });
|
|
111
|
+
* console.log(response.message.content);
|
|
112
|
+
* console.log(response.sources); // retrieved context
|
|
113
|
+
*/
|
|
114
|
+
rag(request: RagRequest): Promise<RagResponse>;
|
|
115
|
+
/**
|
|
116
|
+
* Stream RAG responses with automatic memory context
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* for await (const chunk of cencori.ai.ragStream({ model: 'gpt-4o', messages, namespace: 'docs' })) {
|
|
120
|
+
* if (chunk.type === 'sources') console.log('Sources:', chunk.sources);
|
|
121
|
+
* if (chunk.type === 'content') process.stdout.write(chunk.delta);
|
|
122
|
+
* }
|
|
123
|
+
*/
|
|
124
|
+
ragStream(request: RagRequest): AsyncGenerator<RagStreamChunk, void, unknown>;
|
|
125
|
+
}
|
|
126
|
+
interface RagRequest {
|
|
127
|
+
model: string;
|
|
128
|
+
messages: Array<{
|
|
129
|
+
role: 'system' | 'user' | 'assistant';
|
|
130
|
+
content: string;
|
|
131
|
+
}>;
|
|
132
|
+
namespace: string;
|
|
133
|
+
temperature?: number;
|
|
134
|
+
maxTokens?: number;
|
|
135
|
+
limit?: number;
|
|
136
|
+
threshold?: number;
|
|
137
|
+
includeSources?: boolean;
|
|
138
|
+
}
|
|
139
|
+
interface RagResponse {
|
|
140
|
+
message: {
|
|
141
|
+
role: string;
|
|
142
|
+
content: string;
|
|
143
|
+
};
|
|
144
|
+
model: string;
|
|
145
|
+
provider: string;
|
|
146
|
+
usage: {
|
|
147
|
+
promptTokens: number;
|
|
148
|
+
completionTokens: number;
|
|
149
|
+
totalTokens: number;
|
|
150
|
+
};
|
|
151
|
+
sources?: Array<{
|
|
152
|
+
content: string;
|
|
153
|
+
metadata: Record<string, unknown>;
|
|
154
|
+
similarity: number;
|
|
155
|
+
}>;
|
|
156
|
+
latencyMs: number;
|
|
157
|
+
}
|
|
158
|
+
interface RagStreamChunk {
|
|
159
|
+
type: 'sources' | 'content';
|
|
160
|
+
delta?: string;
|
|
161
|
+
finish_reason?: string;
|
|
162
|
+
sources?: Array<{
|
|
163
|
+
content: string;
|
|
164
|
+
metadata: Record<string, unknown>;
|
|
165
|
+
similarity: number;
|
|
166
|
+
}>;
|
|
98
167
|
}
|
|
99
168
|
|
|
100
|
-
export { AINamespace, type StreamChunk };
|
|
169
|
+
export { AINamespace, type RagRequest, type RagResponse, type RagStreamChunk, type StreamChunk };
|
package/dist/ai/index.d.ts
CHANGED
|
@@ -95,6 +95,75 @@ declare class AINamespace {
|
|
|
95
95
|
* console.log(response.images[0].url);
|
|
96
96
|
*/
|
|
97
97
|
generateImage(request: ImageGenerationRequest): Promise<ImageGenerationResponse>;
|
|
98
|
+
/**
|
|
99
|
+
* RAG (Retrieval-Augmented Generation) - Chat with automatic memory context
|
|
100
|
+
*
|
|
101
|
+
* Searches your memory namespace for relevant context and includes it
|
|
102
|
+
* in the prompt automatically. Returns the AI response along with sources.
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* const response = await cencori.ai.rag({
|
|
106
|
+
* model: 'gpt-4o',
|
|
107
|
+
* messages: [{ role: 'user', content: 'What are our company policies?' }],
|
|
108
|
+
* namespace: 'company-docs',
|
|
109
|
+
* limit: 5, // number of memories to retrieve
|
|
110
|
+
* });
|
|
111
|
+
* console.log(response.message.content);
|
|
112
|
+
* console.log(response.sources); // retrieved context
|
|
113
|
+
*/
|
|
114
|
+
rag(request: RagRequest): Promise<RagResponse>;
|
|
115
|
+
/**
|
|
116
|
+
* Stream RAG responses with automatic memory context
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* for await (const chunk of cencori.ai.ragStream({ model: 'gpt-4o', messages, namespace: 'docs' })) {
|
|
120
|
+
* if (chunk.type === 'sources') console.log('Sources:', chunk.sources);
|
|
121
|
+
* if (chunk.type === 'content') process.stdout.write(chunk.delta);
|
|
122
|
+
* }
|
|
123
|
+
*/
|
|
124
|
+
ragStream(request: RagRequest): AsyncGenerator<RagStreamChunk, void, unknown>;
|
|
125
|
+
}
|
|
126
|
+
interface RagRequest {
|
|
127
|
+
model: string;
|
|
128
|
+
messages: Array<{
|
|
129
|
+
role: 'system' | 'user' | 'assistant';
|
|
130
|
+
content: string;
|
|
131
|
+
}>;
|
|
132
|
+
namespace: string;
|
|
133
|
+
temperature?: number;
|
|
134
|
+
maxTokens?: number;
|
|
135
|
+
limit?: number;
|
|
136
|
+
threshold?: number;
|
|
137
|
+
includeSources?: boolean;
|
|
138
|
+
}
|
|
139
|
+
interface RagResponse {
|
|
140
|
+
message: {
|
|
141
|
+
role: string;
|
|
142
|
+
content: string;
|
|
143
|
+
};
|
|
144
|
+
model: string;
|
|
145
|
+
provider: string;
|
|
146
|
+
usage: {
|
|
147
|
+
promptTokens: number;
|
|
148
|
+
completionTokens: number;
|
|
149
|
+
totalTokens: number;
|
|
150
|
+
};
|
|
151
|
+
sources?: Array<{
|
|
152
|
+
content: string;
|
|
153
|
+
metadata: Record<string, unknown>;
|
|
154
|
+
similarity: number;
|
|
155
|
+
}>;
|
|
156
|
+
latencyMs: number;
|
|
157
|
+
}
|
|
158
|
+
interface RagStreamChunk {
|
|
159
|
+
type: 'sources' | 'content';
|
|
160
|
+
delta?: string;
|
|
161
|
+
finish_reason?: string;
|
|
162
|
+
sources?: Array<{
|
|
163
|
+
content: string;
|
|
164
|
+
metadata: Record<string, unknown>;
|
|
165
|
+
similarity: number;
|
|
166
|
+
}>;
|
|
98
167
|
}
|
|
99
168
|
|
|
100
|
-
export { AINamespace, type StreamChunk };
|
|
169
|
+
export { AINamespace, type RagRequest, type RagResponse, type RagStreamChunk, type StreamChunk };
|
package/dist/ai/index.js
CHANGED
|
@@ -312,6 +312,131 @@ var AINamespace = class {
|
|
|
312
312
|
provider: data.provider
|
|
313
313
|
};
|
|
314
314
|
}
|
|
315
|
+
/**
|
|
316
|
+
* RAG (Retrieval-Augmented Generation) - Chat with automatic memory context
|
|
317
|
+
*
|
|
318
|
+
* Searches your memory namespace for relevant context and includes it
|
|
319
|
+
* in the prompt automatically. Returns the AI response along with sources.
|
|
320
|
+
*
|
|
321
|
+
* @example
|
|
322
|
+
* const response = await cencori.ai.rag({
|
|
323
|
+
* model: 'gpt-4o',
|
|
324
|
+
* messages: [{ role: 'user', content: 'What are our company policies?' }],
|
|
325
|
+
* namespace: 'company-docs',
|
|
326
|
+
* limit: 5, // number of memories to retrieve
|
|
327
|
+
* });
|
|
328
|
+
* console.log(response.message.content);
|
|
329
|
+
* console.log(response.sources); // retrieved context
|
|
330
|
+
*/
|
|
331
|
+
async rag(request) {
|
|
332
|
+
const response = await fetch(`${this.config.baseUrl}/api/ai/rag`, {
|
|
333
|
+
method: "POST",
|
|
334
|
+
headers: {
|
|
335
|
+
"CENCORI_API_KEY": this.config.apiKey,
|
|
336
|
+
"Content-Type": "application/json",
|
|
337
|
+
...this.config.headers
|
|
338
|
+
},
|
|
339
|
+
body: JSON.stringify({
|
|
340
|
+
model: request.model,
|
|
341
|
+
messages: request.messages,
|
|
342
|
+
namespace: request.namespace,
|
|
343
|
+
temperature: request.temperature,
|
|
344
|
+
maxTokens: request.maxTokens,
|
|
345
|
+
limit: request.limit ?? 5,
|
|
346
|
+
threshold: request.threshold ?? 0.5,
|
|
347
|
+
include_sources: request.includeSources ?? true,
|
|
348
|
+
stream: false
|
|
349
|
+
})
|
|
350
|
+
});
|
|
351
|
+
if (!response.ok) {
|
|
352
|
+
const errorData = await response.json().catch(() => ({ error: "Unknown error" }));
|
|
353
|
+
throw new Error(`Cencori API error: ${errorData.error || response.statusText}`);
|
|
354
|
+
}
|
|
355
|
+
const data = await response.json();
|
|
356
|
+
return {
|
|
357
|
+
message: {
|
|
358
|
+
role: "assistant",
|
|
359
|
+
content: data.message.content
|
|
360
|
+
},
|
|
361
|
+
model: data.model,
|
|
362
|
+
provider: data.provider,
|
|
363
|
+
usage: {
|
|
364
|
+
promptTokens: data.usage.prompt_tokens,
|
|
365
|
+
completionTokens: data.usage.completion_tokens,
|
|
366
|
+
totalTokens: data.usage.total_tokens
|
|
367
|
+
},
|
|
368
|
+
sources: data.sources?.map((s) => ({
|
|
369
|
+
content: s.content,
|
|
370
|
+
metadata: s.metadata,
|
|
371
|
+
similarity: s.similarity
|
|
372
|
+
})),
|
|
373
|
+
latencyMs: data.latency_ms
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* Stream RAG responses with automatic memory context
|
|
378
|
+
*
|
|
379
|
+
* @example
|
|
380
|
+
* for await (const chunk of cencori.ai.ragStream({ model: 'gpt-4o', messages, namespace: 'docs' })) {
|
|
381
|
+
* if (chunk.type === 'sources') console.log('Sources:', chunk.sources);
|
|
382
|
+
* if (chunk.type === 'content') process.stdout.write(chunk.delta);
|
|
383
|
+
* }
|
|
384
|
+
*/
|
|
385
|
+
async *ragStream(request) {
|
|
386
|
+
const response = await fetch(`${this.config.baseUrl}/api/ai/rag`, {
|
|
387
|
+
method: "POST",
|
|
388
|
+
headers: {
|
|
389
|
+
"CENCORI_API_KEY": this.config.apiKey,
|
|
390
|
+
"Content-Type": "application/json",
|
|
391
|
+
...this.config.headers
|
|
392
|
+
},
|
|
393
|
+
body: JSON.stringify({
|
|
394
|
+
model: request.model,
|
|
395
|
+
messages: request.messages,
|
|
396
|
+
namespace: request.namespace,
|
|
397
|
+
temperature: request.temperature,
|
|
398
|
+
maxTokens: request.maxTokens,
|
|
399
|
+
limit: request.limit ?? 5,
|
|
400
|
+
threshold: request.threshold ?? 0.5,
|
|
401
|
+
include_sources: request.includeSources ?? true,
|
|
402
|
+
stream: true
|
|
403
|
+
})
|
|
404
|
+
});
|
|
405
|
+
if (!response.ok) {
|
|
406
|
+
const errorData = await response.json().catch(() => ({ error: "Unknown error" }));
|
|
407
|
+
throw new Error(`Cencori API error: ${errorData.error || response.statusText}`);
|
|
408
|
+
}
|
|
409
|
+
if (!response.body) {
|
|
410
|
+
throw new Error("Response body is null");
|
|
411
|
+
}
|
|
412
|
+
const reader = response.body.getReader();
|
|
413
|
+
const decoder = new TextDecoder();
|
|
414
|
+
let buffer = "";
|
|
415
|
+
try {
|
|
416
|
+
while (true) {
|
|
417
|
+
const { done, value } = await reader.read();
|
|
418
|
+
if (done) break;
|
|
419
|
+
buffer += decoder.decode(value, { stream: true });
|
|
420
|
+
const lines = buffer.split("\n");
|
|
421
|
+
buffer = lines.pop() || "";
|
|
422
|
+
for (const line of lines) {
|
|
423
|
+
if (line.trim() === "") continue;
|
|
424
|
+
if (!line.startsWith("data: ")) continue;
|
|
425
|
+
const data = line.slice(6);
|
|
426
|
+
if (data === "[DONE]") {
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
try {
|
|
430
|
+
const chunk = JSON.parse(data);
|
|
431
|
+
yield chunk;
|
|
432
|
+
} catch {
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
} finally {
|
|
437
|
+
reader.releaseLock();
|
|
438
|
+
}
|
|
439
|
+
}
|
|
315
440
|
};
|
|
316
441
|
// Annotate the CommonJS export names for ESM import in node:
|
|
317
442
|
0 && (module.exports = {
|
package/dist/ai/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/ai/index.ts"],"sourcesContent":["/**\n * AI Gateway - Chat, Completions, Embeddings, and Streaming\n * \n * @example\n * const response = await cencori.ai.chat({\n * model: 'gpt-4o',\n * messages: [{ role: 'user', content: 'Hello!' }]\n * });\n */\n\nimport type {\n CencoriConfig,\n ChatRequest,\n ChatResponse,\n CompletionRequest,\n EmbeddingRequest,\n EmbeddingResponse,\n GenerateObjectRequest,\n GenerateObjectResponse,\n ImageGenerationRequest,\n ImageGenerationResponse,\n ToolCall\n} from '../types';\n\n// API Response types\ninterface OpenAIChatResponse {\n id: string;\n model: string;\n choices?: Array<{\n message?: {\n content?: string;\n tool_calls?: Array<{\n id: string;\n type: 'function';\n function: {\n name: string;\n arguments: string;\n };\n }>;\n };\n finish_reason?: string;\n }>;\n usage?: {\n prompt_tokens?: number;\n completion_tokens?: number;\n total_tokens?: number;\n };\n}\n\ninterface OpenAIEmbeddingResponse {\n model: string;\n data?: Array<{\n embedding: number[];\n }>;\n usage?: {\n total_tokens?: number;\n };\n}\n\n/**\n * Stream chunk from chat stream\n */\nexport interface StreamChunk {\n delta: string;\n finish_reason?: 'stop' | 'length' | 'content_filter' | 'tool_calls' | 'error';\n /** Tool calls in progress during streaming */\n toolCalls?: ToolCall[];\n /** Error message if the stream encountered an error */\n error?: string;\n}\n\nexport class AINamespace {\n private config: Required<CencoriConfig>;\n\n constructor(config: Required<CencoriConfig>) {\n this.config = config;\n }\n\n /**\n * Create a chat completion\n * \n * @example\n * const response = await cencori.ai.chat({\n * model: 'gpt-4o',\n * messages: [{ role: 'user', content: 'Hello!' }]\n * });\n */\n async chat(request: ChatRequest): Promise<ChatResponse> {\n const response = await fetch(`${this.config.baseUrl}/api/ai/chat`, {\n method: 'POST',\n headers: {\n 'CENCORI_API_KEY': this.config.apiKey,\n 'Content-Type': 'application/json',\n ...this.config.headers,\n },\n body: JSON.stringify({\n model: request.model,\n messages: request.messages,\n temperature: request.temperature,\n maxTokens: request.maxTokens,\n stream: false,\n tools: request.tools,\n toolChoice: request.toolChoice,\n }),\n });\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({ error: 'Unknown error' })) as { error?: string };\n throw new Error(`Cencori API error: ${errorData.error || response.statusText}`);\n }\n\n const data = await response.json() as OpenAIChatResponse;\n\n const choice = data.choices?.[0];\n const toolCalls = choice?.message?.tool_calls?.map(tc => ({\n id: tc.id,\n type: tc.type as 'function',\n function: {\n name: tc.function.name,\n arguments: tc.function.arguments,\n },\n }));\n\n return {\n id: data.id,\n model: data.model,\n content: choice?.message?.content ?? '',\n toolCalls,\n finishReason: choice?.finish_reason as ChatResponse['finishReason'],\n usage: {\n promptTokens: data.usage?.prompt_tokens ?? 0,\n completionTokens: data.usage?.completion_tokens ?? 0,\n totalTokens: data.usage?.total_tokens ?? 0,\n },\n };\n }\n\n /**\n * Stream chat completions\n * Returns an async generator that yields chunks as they arrive\n * \n * @example\n * for await (const chunk of cencori.ai.chatStream({ model: 'gpt-4o', messages })) {\n * process.stdout.write(chunk.delta);\n * }\n */\n async *chatStream(request: ChatRequest): AsyncGenerator<StreamChunk, void, unknown> {\n const response = await fetch(`${this.config.baseUrl}/api/ai/chat`, {\n method: 'POST',\n headers: {\n 'CENCORI_API_KEY': this.config.apiKey,\n 'Content-Type': 'application/json',\n ...this.config.headers,\n },\n body: JSON.stringify({\n model: request.model,\n messages: request.messages,\n temperature: request.temperature,\n maxTokens: request.maxTokens,\n stream: true,\n tools: request.tools,\n toolChoice: request.toolChoice,\n }),\n });\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({ error: 'Unknown error' })) as { error?: string };\n throw new Error(`Cencori API error: ${errorData.error || response.statusText}`);\n }\n\n if (!response.body) {\n throw new Error('Response body is null');\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n\n // Keep the last incomplete line in the buffer\n buffer = lines.pop() || '';\n\n for (const line of lines) {\n if (line.trim() === '') continue;\n if (!line.startsWith('data: ')) continue;\n\n const data = line.slice(6); // Remove 'data: ' prefix\n\n if (data === '[DONE]') {\n return;\n }\n\n try {\n const chunk = JSON.parse(data) as StreamChunk;\n yield chunk;\n } catch {\n // Skip malformed JSON\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n }\n\n /**\n * Create a text completion\n * \n * @example\n * const response = await cencori.ai.completions({\n * model: 'gpt-4o',\n * prompt: 'Write a haiku about coding'\n * });\n */\n async completions(request: CompletionRequest): Promise<ChatResponse> {\n // Convert to chat format internally\n return this.chat({\n model: request.model,\n messages: [{ role: 'user', content: request.prompt }],\n temperature: request.temperature,\n maxTokens: request.maxTokens,\n });\n }\n\n /**\n * Create embeddings\n * \n * @example\n * const response = await cencori.ai.embeddings({\n * model: 'text-embedding-3-small',\n * input: 'Hello world'\n * });\n */\n async embeddings(request: EmbeddingRequest): Promise<EmbeddingResponse> {\n const response = await fetch(`${this.config.baseUrl}/api/ai/embeddings`, {\n method: 'POST',\n headers: {\n 'CENCORI_API_KEY': this.config.apiKey,\n 'Content-Type': 'application/json',\n ...this.config.headers,\n },\n body: JSON.stringify({\n model: request.model,\n input: request.input,\n }),\n });\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({ error: 'Unknown error' })) as { error?: string };\n throw new Error(`Cencori API error: ${errorData.error || response.statusText}`);\n }\n\n const data = await response.json() as OpenAIEmbeddingResponse;\n\n return {\n model: data.model,\n embeddings: data.data?.map((d) => d.embedding) ?? [],\n usage: {\n totalTokens: data.usage?.total_tokens ?? 0,\n },\n };\n }\n\n /**\n * Generate structured output with JSON schema\n * \n * @example\n * const response = await cencori.ai.generateObject({\n * model: 'gpt-4o',\n * prompt: 'Generate a user profile',\n * schema: {\n * type: 'object',\n * properties: {\n * name: { type: 'string' },\n * age: { type: 'number' }\n * },\n * required: ['name', 'age']\n * }\n * });\n * console.log(response.object); // { name: 'John', age: 30 }\n */\n async generateObject<T = unknown>(request: GenerateObjectRequest): Promise<GenerateObjectResponse<T>> {\n // Build messages from prompt or use provided messages\n const messages = request.messages ?? [\n { role: 'user' as const, content: request.prompt ?? '' }\n ];\n\n // Use function calling to enforce JSON schema\n const response = await fetch(`${this.config.baseUrl}/api/ai/chat`, {\n method: 'POST',\n headers: {\n 'CENCORI_API_KEY': this.config.apiKey,\n 'Content-Type': 'application/json',\n ...this.config.headers,\n },\n body: JSON.stringify({\n model: request.model,\n messages,\n temperature: request.temperature,\n maxTokens: request.maxTokens,\n stream: false,\n tools: [{\n type: 'function',\n function: {\n name: request.schemaName ?? 'generate_object',\n description: request.schemaDescription ?? 'Generate a structured object matching the schema',\n parameters: request.schema,\n },\n }],\n toolChoice: {\n type: 'function',\n function: { name: request.schemaName ?? 'generate_object' },\n },\n }),\n });\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({ error: 'Unknown error' })) as { error?: string };\n throw new Error(`Cencori API error: ${errorData.error || response.statusText}`);\n }\n\n const data = await response.json() as OpenAIChatResponse;\n const toolCall = data.choices?.[0]?.message?.tool_calls?.[0];\n\n if (!toolCall) {\n throw new Error('Model did not return structured output');\n }\n\n let parsedObject: T;\n try {\n parsedObject = JSON.parse(toolCall.function.arguments) as T;\n } catch {\n throw new Error('Failed to parse structured output as JSON');\n }\n\n return {\n object: parsedObject,\n usage: {\n promptTokens: data.usage?.prompt_tokens ?? 0,\n completionTokens: data.usage?.completion_tokens ?? 0,\n totalTokens: data.usage?.total_tokens ?? 0,\n },\n };\n }\n\n /**\n * Generate images from a text prompt\n * \n * @example\n * const response = await cencori.ai.generateImage({\n * prompt: 'A futuristic city at sunset',\n * model: 'dall-e-3',\n * size: '1024x1024'\n * });\n * console.log(response.images[0].url);\n */\n async generateImage(request: ImageGenerationRequest): Promise<ImageGenerationResponse> {\n const response = await fetch(`${this.config.baseUrl}/api/ai/images/generate`, {\n method: 'POST',\n headers: {\n 'CENCORI_API_KEY': this.config.apiKey,\n 'Content-Type': 'application/json',\n ...this.config.headers,\n },\n body: JSON.stringify({\n prompt: request.prompt,\n model: request.model ?? 'dall-e-3',\n n: request.n,\n size: request.size,\n quality: request.quality,\n style: request.style,\n responseFormat: request.responseFormat,\n }),\n });\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({ error: 'Unknown error' })) as { error?: string; message?: string };\n throw new Error(`Cencori API error: ${errorData.message || errorData.error || response.statusText}`);\n }\n\n const data = await response.json() as {\n images: Array<{ url?: string; b64_json?: string; revisedPrompt?: string }>;\n model: string;\n provider: string;\n };\n\n return {\n images: data.images.map(img => ({\n url: img.url,\n b64Json: img.b64_json,\n revisedPrompt: img.revisedPrompt,\n })),\n model: data.model,\n provider: data.provider,\n };\n }\n}\n\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/ai/index.ts"],"sourcesContent":["/**\n * AI Gateway - Chat, Completions, Embeddings, and Streaming\n * \n * @example\n * const response = await cencori.ai.chat({\n * model: 'gpt-4o',\n * messages: [{ role: 'user', content: 'Hello!' }]\n * });\n */\n\nimport type {\n CencoriConfig,\n ChatRequest,\n ChatResponse,\n CompletionRequest,\n EmbeddingRequest,\n EmbeddingResponse,\n GenerateObjectRequest,\n GenerateObjectResponse,\n ImageGenerationRequest,\n ImageGenerationResponse,\n ToolCall\n} from '../types';\n\n// API Response types\ninterface OpenAIChatResponse {\n id: string;\n model: string;\n choices?: Array<{\n message?: {\n content?: string;\n tool_calls?: Array<{\n id: string;\n type: 'function';\n function: {\n name: string;\n arguments: string;\n };\n }>;\n };\n finish_reason?: string;\n }>;\n usage?: {\n prompt_tokens?: number;\n completion_tokens?: number;\n total_tokens?: number;\n };\n}\n\ninterface OpenAIEmbeddingResponse {\n model: string;\n data?: Array<{\n embedding: number[];\n }>;\n usage?: {\n total_tokens?: number;\n };\n}\n\n/**\n * Stream chunk from chat stream\n */\nexport interface StreamChunk {\n delta: string;\n finish_reason?: 'stop' | 'length' | 'content_filter' | 'tool_calls' | 'error';\n /** Tool calls in progress during streaming */\n toolCalls?: ToolCall[];\n /** Error message if the stream encountered an error */\n error?: string;\n}\n\nexport class AINamespace {\n private config: Required<CencoriConfig>;\n\n constructor(config: Required<CencoriConfig>) {\n this.config = config;\n }\n\n /**\n * Create a chat completion\n * \n * @example\n * const response = await cencori.ai.chat({\n * model: 'gpt-4o',\n * messages: [{ role: 'user', content: 'Hello!' }]\n * });\n */\n async chat(request: ChatRequest): Promise<ChatResponse> {\n const response = await fetch(`${this.config.baseUrl}/api/ai/chat`, {\n method: 'POST',\n headers: {\n 'CENCORI_API_KEY': this.config.apiKey,\n 'Content-Type': 'application/json',\n ...this.config.headers,\n },\n body: JSON.stringify({\n model: request.model,\n messages: request.messages,\n temperature: request.temperature,\n maxTokens: request.maxTokens,\n stream: false,\n tools: request.tools,\n toolChoice: request.toolChoice,\n }),\n });\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({ error: 'Unknown error' })) as { error?: string };\n throw new Error(`Cencori API error: ${errorData.error || response.statusText}`);\n }\n\n const data = await response.json() as OpenAIChatResponse;\n\n const choice = data.choices?.[0];\n const toolCalls = choice?.message?.tool_calls?.map(tc => ({\n id: tc.id,\n type: tc.type as 'function',\n function: {\n name: tc.function.name,\n arguments: tc.function.arguments,\n },\n }));\n\n return {\n id: data.id,\n model: data.model,\n content: choice?.message?.content ?? '',\n toolCalls,\n finishReason: choice?.finish_reason as ChatResponse['finishReason'],\n usage: {\n promptTokens: data.usage?.prompt_tokens ?? 0,\n completionTokens: data.usage?.completion_tokens ?? 0,\n totalTokens: data.usage?.total_tokens ?? 0,\n },\n };\n }\n\n /**\n * Stream chat completions\n * Returns an async generator that yields chunks as they arrive\n * \n * @example\n * for await (const chunk of cencori.ai.chatStream({ model: 'gpt-4o', messages })) {\n * process.stdout.write(chunk.delta);\n * }\n */\n async *chatStream(request: ChatRequest): AsyncGenerator<StreamChunk, void, unknown> {\n const response = await fetch(`${this.config.baseUrl}/api/ai/chat`, {\n method: 'POST',\n headers: {\n 'CENCORI_API_KEY': this.config.apiKey,\n 'Content-Type': 'application/json',\n ...this.config.headers,\n },\n body: JSON.stringify({\n model: request.model,\n messages: request.messages,\n temperature: request.temperature,\n maxTokens: request.maxTokens,\n stream: true,\n tools: request.tools,\n toolChoice: request.toolChoice,\n }),\n });\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({ error: 'Unknown error' })) as { error?: string };\n throw new Error(`Cencori API error: ${errorData.error || response.statusText}`);\n }\n\n if (!response.body) {\n throw new Error('Response body is null');\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n\n // Keep the last incomplete line in the buffer\n buffer = lines.pop() || '';\n\n for (const line of lines) {\n if (line.trim() === '') continue;\n if (!line.startsWith('data: ')) continue;\n\n const data = line.slice(6); // Remove 'data: ' prefix\n\n if (data === '[DONE]') {\n return;\n }\n\n try {\n const chunk = JSON.parse(data) as StreamChunk;\n yield chunk;\n } catch {\n // Skip malformed JSON\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n }\n\n /**\n * Create a text completion\n * \n * @example\n * const response = await cencori.ai.completions({\n * model: 'gpt-4o',\n * prompt: 'Write a haiku about coding'\n * });\n */\n async completions(request: CompletionRequest): Promise<ChatResponse> {\n // Convert to chat format internally\n return this.chat({\n model: request.model,\n messages: [{ role: 'user', content: request.prompt }],\n temperature: request.temperature,\n maxTokens: request.maxTokens,\n });\n }\n\n /**\n * Create embeddings\n * \n * @example\n * const response = await cencori.ai.embeddings({\n * model: 'text-embedding-3-small',\n * input: 'Hello world'\n * });\n */\n async embeddings(request: EmbeddingRequest): Promise<EmbeddingResponse> {\n const response = await fetch(`${this.config.baseUrl}/api/ai/embeddings`, {\n method: 'POST',\n headers: {\n 'CENCORI_API_KEY': this.config.apiKey,\n 'Content-Type': 'application/json',\n ...this.config.headers,\n },\n body: JSON.stringify({\n model: request.model,\n input: request.input,\n }),\n });\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({ error: 'Unknown error' })) as { error?: string };\n throw new Error(`Cencori API error: ${errorData.error || response.statusText}`);\n }\n\n const data = await response.json() as OpenAIEmbeddingResponse;\n\n return {\n model: data.model,\n embeddings: data.data?.map((d) => d.embedding) ?? [],\n usage: {\n totalTokens: data.usage?.total_tokens ?? 0,\n },\n };\n }\n\n /**\n * Generate structured output with JSON schema\n * \n * @example\n * const response = await cencori.ai.generateObject({\n * model: 'gpt-4o',\n * prompt: 'Generate a user profile',\n * schema: {\n * type: 'object',\n * properties: {\n * name: { type: 'string' },\n * age: { type: 'number' }\n * },\n * required: ['name', 'age']\n * }\n * });\n * console.log(response.object); // { name: 'John', age: 30 }\n */\n async generateObject<T = unknown>(request: GenerateObjectRequest): Promise<GenerateObjectResponse<T>> {\n // Build messages from prompt or use provided messages\n const messages = request.messages ?? [\n { role: 'user' as const, content: request.prompt ?? '' }\n ];\n\n // Use function calling to enforce JSON schema\n const response = await fetch(`${this.config.baseUrl}/api/ai/chat`, {\n method: 'POST',\n headers: {\n 'CENCORI_API_KEY': this.config.apiKey,\n 'Content-Type': 'application/json',\n ...this.config.headers,\n },\n body: JSON.stringify({\n model: request.model,\n messages,\n temperature: request.temperature,\n maxTokens: request.maxTokens,\n stream: false,\n tools: [{\n type: 'function',\n function: {\n name: request.schemaName ?? 'generate_object',\n description: request.schemaDescription ?? 'Generate a structured object matching the schema',\n parameters: request.schema,\n },\n }],\n toolChoice: {\n type: 'function',\n function: { name: request.schemaName ?? 'generate_object' },\n },\n }),\n });\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({ error: 'Unknown error' })) as { error?: string };\n throw new Error(`Cencori API error: ${errorData.error || response.statusText}`);\n }\n\n const data = await response.json() as OpenAIChatResponse;\n const toolCall = data.choices?.[0]?.message?.tool_calls?.[0];\n\n if (!toolCall) {\n throw new Error('Model did not return structured output');\n }\n\n let parsedObject: T;\n try {\n parsedObject = JSON.parse(toolCall.function.arguments) as T;\n } catch {\n throw new Error('Failed to parse structured output as JSON');\n }\n\n return {\n object: parsedObject,\n usage: {\n promptTokens: data.usage?.prompt_tokens ?? 0,\n completionTokens: data.usage?.completion_tokens ?? 0,\n totalTokens: data.usage?.total_tokens ?? 0,\n },\n };\n }\n\n /**\n * Generate images from a text prompt\n * \n * @example\n * const response = await cencori.ai.generateImage({\n * prompt: 'A futuristic city at sunset',\n * model: 'dall-e-3',\n * size: '1024x1024'\n * });\n * console.log(response.images[0].url);\n */\n async generateImage(request: ImageGenerationRequest): Promise<ImageGenerationResponse> {\n const response = await fetch(`${this.config.baseUrl}/api/ai/images/generate`, {\n method: 'POST',\n headers: {\n 'CENCORI_API_KEY': this.config.apiKey,\n 'Content-Type': 'application/json',\n ...this.config.headers,\n },\n body: JSON.stringify({\n prompt: request.prompt,\n model: request.model ?? 'dall-e-3',\n n: request.n,\n size: request.size,\n quality: request.quality,\n style: request.style,\n responseFormat: request.responseFormat,\n }),\n });\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({ error: 'Unknown error' })) as { error?: string; message?: string };\n throw new Error(`Cencori API error: ${errorData.message || errorData.error || response.statusText}`);\n }\n\n const data = await response.json() as {\n images: Array<{ url?: string; b64_json?: string; revisedPrompt?: string }>;\n model: string;\n provider: string;\n };\n\n return {\n images: data.images.map(img => ({\n url: img.url,\n b64Json: img.b64_json,\n revisedPrompt: img.revisedPrompt,\n })),\n model: data.model,\n provider: data.provider,\n };\n }\n\n /**\n * RAG (Retrieval-Augmented Generation) - Chat with automatic memory context\n * \n * Searches your memory namespace for relevant context and includes it\n * in the prompt automatically. Returns the AI response along with sources.\n * \n * @example\n * const response = await cencori.ai.rag({\n * model: 'gpt-4o',\n * messages: [{ role: 'user', content: 'What are our company policies?' }],\n * namespace: 'company-docs',\n * limit: 5, // number of memories to retrieve\n * });\n * console.log(response.message.content);\n * console.log(response.sources); // retrieved context\n */\n async rag(request: RagRequest): Promise<RagResponse> {\n const response = await fetch(`${this.config.baseUrl}/api/ai/rag`, {\n method: 'POST',\n headers: {\n 'CENCORI_API_KEY': this.config.apiKey,\n 'Content-Type': 'application/json',\n ...this.config.headers,\n },\n body: JSON.stringify({\n model: request.model,\n messages: request.messages,\n namespace: request.namespace,\n temperature: request.temperature,\n maxTokens: request.maxTokens,\n limit: request.limit ?? 5,\n threshold: request.threshold ?? 0.5,\n include_sources: request.includeSources ?? true,\n stream: false,\n }),\n });\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({ error: 'Unknown error' })) as { error?: string };\n throw new Error(`Cencori API error: ${errorData.error || response.statusText}`);\n }\n\n const data = await response.json() as RagApiResponse;\n\n return {\n message: {\n role: 'assistant',\n content: data.message.content,\n },\n model: data.model,\n provider: data.provider,\n usage: {\n promptTokens: data.usage.prompt_tokens,\n completionTokens: data.usage.completion_tokens,\n totalTokens: data.usage.total_tokens,\n },\n sources: data.sources?.map(s => ({\n content: s.content,\n metadata: s.metadata,\n similarity: s.similarity,\n })),\n latencyMs: data.latency_ms,\n };\n }\n\n /**\n * Stream RAG responses with automatic memory context\n * \n * @example\n * for await (const chunk of cencori.ai.ragStream({ model: 'gpt-4o', messages, namespace: 'docs' })) {\n * if (chunk.type === 'sources') console.log('Sources:', chunk.sources);\n * if (chunk.type === 'content') process.stdout.write(chunk.delta);\n * }\n */\n async *ragStream(request: RagRequest): AsyncGenerator<RagStreamChunk, void, unknown> {\n const response = await fetch(`${this.config.baseUrl}/api/ai/rag`, {\n method: 'POST',\n headers: {\n 'CENCORI_API_KEY': this.config.apiKey,\n 'Content-Type': 'application/json',\n ...this.config.headers,\n },\n body: JSON.stringify({\n model: request.model,\n messages: request.messages,\n namespace: request.namespace,\n temperature: request.temperature,\n maxTokens: request.maxTokens,\n limit: request.limit ?? 5,\n threshold: request.threshold ?? 0.5,\n include_sources: request.includeSources ?? true,\n stream: true,\n }),\n });\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({ error: 'Unknown error' })) as { error?: string };\n throw new Error(`Cencori API error: ${errorData.error || response.statusText}`);\n }\n\n if (!response.body) {\n throw new Error('Response body is null');\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() || '';\n\n for (const line of lines) {\n if (line.trim() === '') continue;\n if (!line.startsWith('data: ')) continue;\n\n const data = line.slice(6);\n\n if (data === '[DONE]') {\n return;\n }\n\n try {\n const chunk = JSON.parse(data) as RagStreamChunk;\n yield chunk;\n } catch {\n // Skip malformed JSON\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n }\n}\n\n// RAG Types\nexport interface RagRequest {\n model: string;\n messages: Array<{ role: 'system' | 'user' | 'assistant'; content: string }>;\n namespace: string;\n temperature?: number;\n maxTokens?: number;\n limit?: number;\n threshold?: number;\n includeSources?: boolean;\n}\n\nexport interface RagResponse {\n message: { role: string; content: string };\n model: string;\n provider: string;\n usage: {\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n };\n sources?: Array<{\n content: string;\n metadata: Record<string, unknown>;\n similarity: number;\n }>;\n latencyMs: number;\n}\n\nexport interface RagStreamChunk {\n type: 'sources' | 'content';\n delta?: string;\n finish_reason?: string;\n sources?: Array<{\n content: string;\n metadata: Record<string, unknown>;\n similarity: number;\n }>;\n}\n\ninterface RagApiResponse {\n message: { role: string; content: string };\n model: string;\n provider: string;\n usage: {\n prompt_tokens: number;\n completion_tokens: number;\n total_tokens: number;\n };\n sources?: Array<{\n content: string;\n metadata: Record<string, unknown>;\n similarity: number;\n }>;\n latency_ms: number;\n}\n"],"mappings":"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","names":[]}
|
package/dist/ai/index.mjs
CHANGED
|
@@ -288,6 +288,131 @@ var AINamespace = class {
|
|
|
288
288
|
provider: data.provider
|
|
289
289
|
};
|
|
290
290
|
}
|
|
291
|
+
/**
|
|
292
|
+
* RAG (Retrieval-Augmented Generation) - Chat with automatic memory context
|
|
293
|
+
*
|
|
294
|
+
* Searches your memory namespace for relevant context and includes it
|
|
295
|
+
* in the prompt automatically. Returns the AI response along with sources.
|
|
296
|
+
*
|
|
297
|
+
* @example
|
|
298
|
+
* const response = await cencori.ai.rag({
|
|
299
|
+
* model: 'gpt-4o',
|
|
300
|
+
* messages: [{ role: 'user', content: 'What are our company policies?' }],
|
|
301
|
+
* namespace: 'company-docs',
|
|
302
|
+
* limit: 5, // number of memories to retrieve
|
|
303
|
+
* });
|
|
304
|
+
* console.log(response.message.content);
|
|
305
|
+
* console.log(response.sources); // retrieved context
|
|
306
|
+
*/
|
|
307
|
+
async rag(request) {
|
|
308
|
+
const response = await fetch(`${this.config.baseUrl}/api/ai/rag`, {
|
|
309
|
+
method: "POST",
|
|
310
|
+
headers: {
|
|
311
|
+
"CENCORI_API_KEY": this.config.apiKey,
|
|
312
|
+
"Content-Type": "application/json",
|
|
313
|
+
...this.config.headers
|
|
314
|
+
},
|
|
315
|
+
body: JSON.stringify({
|
|
316
|
+
model: request.model,
|
|
317
|
+
messages: request.messages,
|
|
318
|
+
namespace: request.namespace,
|
|
319
|
+
temperature: request.temperature,
|
|
320
|
+
maxTokens: request.maxTokens,
|
|
321
|
+
limit: request.limit ?? 5,
|
|
322
|
+
threshold: request.threshold ?? 0.5,
|
|
323
|
+
include_sources: request.includeSources ?? true,
|
|
324
|
+
stream: false
|
|
325
|
+
})
|
|
326
|
+
});
|
|
327
|
+
if (!response.ok) {
|
|
328
|
+
const errorData = await response.json().catch(() => ({ error: "Unknown error" }));
|
|
329
|
+
throw new Error(`Cencori API error: ${errorData.error || response.statusText}`);
|
|
330
|
+
}
|
|
331
|
+
const data = await response.json();
|
|
332
|
+
return {
|
|
333
|
+
message: {
|
|
334
|
+
role: "assistant",
|
|
335
|
+
content: data.message.content
|
|
336
|
+
},
|
|
337
|
+
model: data.model,
|
|
338
|
+
provider: data.provider,
|
|
339
|
+
usage: {
|
|
340
|
+
promptTokens: data.usage.prompt_tokens,
|
|
341
|
+
completionTokens: data.usage.completion_tokens,
|
|
342
|
+
totalTokens: data.usage.total_tokens
|
|
343
|
+
},
|
|
344
|
+
sources: data.sources?.map((s) => ({
|
|
345
|
+
content: s.content,
|
|
346
|
+
metadata: s.metadata,
|
|
347
|
+
similarity: s.similarity
|
|
348
|
+
})),
|
|
349
|
+
latencyMs: data.latency_ms
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Stream RAG responses with automatic memory context
|
|
354
|
+
*
|
|
355
|
+
* @example
|
|
356
|
+
* for await (const chunk of cencori.ai.ragStream({ model: 'gpt-4o', messages, namespace: 'docs' })) {
|
|
357
|
+
* if (chunk.type === 'sources') console.log('Sources:', chunk.sources);
|
|
358
|
+
* if (chunk.type === 'content') process.stdout.write(chunk.delta);
|
|
359
|
+
* }
|
|
360
|
+
*/
|
|
361
|
+
async *ragStream(request) {
|
|
362
|
+
const response = await fetch(`${this.config.baseUrl}/api/ai/rag`, {
|
|
363
|
+
method: "POST",
|
|
364
|
+
headers: {
|
|
365
|
+
"CENCORI_API_KEY": this.config.apiKey,
|
|
366
|
+
"Content-Type": "application/json",
|
|
367
|
+
...this.config.headers
|
|
368
|
+
},
|
|
369
|
+
body: JSON.stringify({
|
|
370
|
+
model: request.model,
|
|
371
|
+
messages: request.messages,
|
|
372
|
+
namespace: request.namespace,
|
|
373
|
+
temperature: request.temperature,
|
|
374
|
+
maxTokens: request.maxTokens,
|
|
375
|
+
limit: request.limit ?? 5,
|
|
376
|
+
threshold: request.threshold ?? 0.5,
|
|
377
|
+
include_sources: request.includeSources ?? true,
|
|
378
|
+
stream: true
|
|
379
|
+
})
|
|
380
|
+
});
|
|
381
|
+
if (!response.ok) {
|
|
382
|
+
const errorData = await response.json().catch(() => ({ error: "Unknown error" }));
|
|
383
|
+
throw new Error(`Cencori API error: ${errorData.error || response.statusText}`);
|
|
384
|
+
}
|
|
385
|
+
if (!response.body) {
|
|
386
|
+
throw new Error("Response body is null");
|
|
387
|
+
}
|
|
388
|
+
const reader = response.body.getReader();
|
|
389
|
+
const decoder = new TextDecoder();
|
|
390
|
+
let buffer = "";
|
|
391
|
+
try {
|
|
392
|
+
while (true) {
|
|
393
|
+
const { done, value } = await reader.read();
|
|
394
|
+
if (done) break;
|
|
395
|
+
buffer += decoder.decode(value, { stream: true });
|
|
396
|
+
const lines = buffer.split("\n");
|
|
397
|
+
buffer = lines.pop() || "";
|
|
398
|
+
for (const line of lines) {
|
|
399
|
+
if (line.trim() === "") continue;
|
|
400
|
+
if (!line.startsWith("data: ")) continue;
|
|
401
|
+
const data = line.slice(6);
|
|
402
|
+
if (data === "[DONE]") {
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
try {
|
|
406
|
+
const chunk = JSON.parse(data);
|
|
407
|
+
yield chunk;
|
|
408
|
+
} catch {
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
} finally {
|
|
413
|
+
reader.releaseLock();
|
|
414
|
+
}
|
|
415
|
+
}
|
|
291
416
|
};
|
|
292
417
|
export {
|
|
293
418
|
AINamespace
|