ai-world-sdk 1.2.6 → 1.2.7

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 CHANGED
@@ -1,1805 +1 @@
1
1
  # ai-world-sdk
2
-
3
- TypeScript SDK for AI World Platform - 一个功能完整的 AI 应用开发 SDK
4
-
5
- [![npm version](https://img.shields.io/npm/v/ai-world-sdk)](https://www.npmjs.com/package/ai-world-sdk)
6
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
-
8
- ## 特性
9
-
10
- - 🤖 **聊天模型**: 兼容 LangChain.js 接口(OpenAI、Gemini、Claude、Doubao)
11
- - 🎨 **图像生成**: 支持豆包 Seedream 和 Google Gemini
12
- - 🎬 **视频生成**: 支持豆包 Seedance 和 OpenAI Sora
13
- - 📥 **下载代理**: 支持流式下载和普通下载任意 URL 的二进制文件
14
- - 🔐 **用户认证**: 支持获取当前登录用户信息
15
- - ⚙️ **全局配置**: 自动从浏览器环境获取配置,简化初始化
16
- - 🐛 **调试模式**: 支持详细的请求/响应日志
17
-
18
- ## 安装
19
-
20
- ```bash
21
- npm install ai-world-sdk
22
- # 或 yarn add ai-world-sdk
23
- # 或 pnpm add ai-world-sdk
24
- ```
25
-
26
- ## 快速开始
27
-
28
- ### 1. 配置(推荐)
29
-
30
- ```typescript
31
- import { sdkConfig } from 'ai-world-sdk';
32
-
33
- // 设置全局配置(只需一次)
34
- sdkConfig.setBaseUrl('your-base-url');
35
- sdkConfig.setToken('your-jwt-token');
36
- sdkConfig.setDebug(true); // 可选:启用调试模式
37
-
38
- // 浏览器环境会自动从 window.location.origin 和 cookie 获取配置
39
- ```
40
-
41
- ### 2. 聊天模型
42
-
43
- ```typescript
44
- import { ChatGoogleGenerativeAI, ChatOpenAI, ChatAnthropic, HumanMessage, SystemMessage } from 'ai-world-sdk';
45
-
46
- // Gemini 模型(使用 gemini provider)
47
- const geminiModel = new ChatGoogleGenerativeAI({
48
- modelName: 'gemini-2.5-flash-image',
49
- temperature: 0.7,
50
- provider: 'gemini', // 或 'api2img'
51
- vertexai: false, // 可选:是否使用 VertexAI(仅当 provider 为 gemini 时有效)
52
- jsonSchema: undefined, // 可选:结构化输出 JSON Schema
53
- webSearch: false, // 可选:若模型支持联网搜索,设为 true 可基于实时网络信息回答
54
- });
55
-
56
- // GPT 模型(使用 api2img provider)
57
- const gptModel = new ChatOpenAI({
58
- modelName: 'gpt-4o-mini',
59
- temperature: 0.7,
60
- provider: 'api2img',
61
- jsonSchema: undefined, // 可选:结构化输出 JSON Schema
62
- webSearch: false, // 可选:若模型支持联网搜索,设为 true 可基于实时网络信息回答
63
- });
64
-
65
- // Claude 模型(使用 api2img provider)
66
- const claudeModel = new ChatAnthropic({
67
- modelName: 'claude-3-sonnet-20240229',
68
- temperature: 0.7,
69
- provider: 'api2img',
70
- });
71
-
72
- // 非流式调用
73
- const response = await geminiModel.invoke([
74
- new SystemMessage('You are a helpful assistant.'),
75
- new HumanMessage('Hello! What is AI?'),
76
- ]);
77
- console.log(response.content);
78
-
79
- // 流式调用
80
- for await (const chunk of geminiModel.stream([
81
- new HumanMessage('Tell me a story'),
82
- ])) {
83
- // 使用 text 属性获取文本内容(推荐)
84
- process.stdout.write(chunk.text);
85
- }
86
- ```
87
-
88
- ### 3. 图像生成
89
-
90
- ```typescript
91
- import { DoubaoImageGenerationClient, GeminiImageGenerationClient } from 'ai-world-sdk';
92
-
93
- // 豆包图像生成
94
- const doubaoClient = new DoubaoImageGenerationClient({});
95
- const result = await doubaoClient.generate({
96
- prompt: 'A beautiful sunset over the ocean',
97
- size: '2K', // 或使用 '2K', '4K' 等
98
- quality: 'hd',
99
- n: 1,
100
- });
101
- console.log('图像 URL:', result.data[0]?.url);
102
-
103
- // Gemini 图像生成
104
- const geminiClient = new GeminiImageGenerationClient({});
105
- const geminiResult = await geminiClient.generate({
106
- prompt: 'A futuristic city',
107
- model: 'gemini-3-pro-image-preview', // 使用 Gemini 3 Pro 模型
108
- aspect_ratio: '16:9',
109
- image_size: '2K', // 仅适用于 gemini-3-pro-image-preview
110
- response_modalities: ['IMAGE'], // 仅返回图片,不返回文本
111
- });
112
- console.log('图像 URL:', geminiResult.data[0]?.url);
113
- ```
114
-
115
- ### 4. 视频生成
116
-
117
- #### 豆包视频生成(Seedance)
118
-
119
- ```typescript
120
- import { VideoGenerationClient } from 'ai-world-sdk';
121
-
122
- const videoClient = new VideoGenerationClient({});
123
-
124
- // 创建任务
125
- const task = await videoClient.create({
126
- prompt: 'A beautiful sunset over the ocean',
127
- duration: 5,
128
- aspect_ratio: '16:9',
129
- });
130
-
131
- // 轮询直到完成
132
- const result = await videoClient.poll(task.id, {
133
- interval: 3000,
134
- timeout: 300000,
135
- });
136
-
137
- if (result.status === 'succeeded') {
138
- console.log('视频 URL:', result.content?.video_url);
139
- }
140
- ```
141
-
142
- #### OpenAI 视频生成(Sora)
143
-
144
- ```typescript
145
- import { OpenAIVideoGenerationClient } from 'ai-world-sdk';
146
-
147
- const openaiVideoClient = new OpenAIVideoGenerationClient({});
148
-
149
- // 方式1: 文本生成视频
150
- const task = await openaiVideoClient.generate({
151
- prompt: 'A beautiful sunset over the ocean with waves crashing on the shore',
152
- model: 'sora-2', // 或 'sora-2-pro'
153
- provider: 'api2img',
154
- seconds: '4', // 4, 8, 或 12 秒
155
- size: '1280x720' // '720x1280', '1280x720', '1024x1792', '1792x1024'
156
- });
157
-
158
- console.log('任务 ID:', task.id);
159
- console.log('任务状态:', task.status);
160
-
161
- // 方式2: 图像生成视频(图生视频)
162
- const taskWithImage = await openaiVideoClient.generate({
163
- prompt: 'Animate this scene with gentle movements',
164
- input_reference: 'data:image/png;base64,iVBORw0KGgo...', // Base64 图像或 URL
165
- model: 'sora-2',
166
- provider: 'api2img',
167
- seconds: '4'
168
- });
169
-
170
- // 查询任务状态
171
- const status = await openaiVideoClient.getTask(task.id, 'api2img');
172
- console.log('当前状态:', status.status);
173
-
174
- // 轮询等待完成
175
- const result = await openaiVideoClient.waitForCompletion(task.id, 'api2img', {
176
- maxAttempts: 60,
177
- interval: 5000,
178
- onProgress: (status) => {
179
- console.log('当前状态:', status.status);
180
- }
181
- });
182
-
183
- if (result.status === 'completed') {
184
- console.log('视频生成成功!');
185
-
186
- // 流式下载视频
187
- const videoBlob = await openaiVideoClient.downloadVideo(
188
- result.id,
189
- 'api2img', // provider
190
- 'video' // 'video' 或 'thumbnail'
191
- );
192
-
193
- console.log('视频大小:', (videoBlob.size / 1024 / 1024).toFixed(2), 'MB');
194
-
195
- // 在浏览器中下载
196
- const url = URL.createObjectURL(videoBlob);
197
- const a = document.createElement('a');
198
- a.href = url;
199
- a.download = 'sora_video.mp4';
200
- a.click();
201
- URL.revokeObjectURL(url);
202
- }
203
-
204
- // 一键生成并等待(简化版)
205
- const completeResult = await openaiVideoClient.generateAndWait({
206
- prompt: 'A futuristic city skyline',
207
- model: 'sora-2',
208
- provider: 'api2img',
209
- seconds: '4'
210
- }, {
211
- maxAttempts: 60,
212
- interval: 5000,
213
- onProgress: (status) => console.log('状态:', status.status)
214
- });
215
-
216
- if (completeResult.status === 'completed') {
217
- const videoBlob = await openaiVideoClient.downloadVideo(
218
- completeResult.id,
219
- 'api2img',
220
- 'video'
221
- );
222
- console.log('一键生成完成,视频大小:', videoBlob.size);
223
- }
224
- ```
225
-
226
- ### 5. 用户认证
227
-
228
- ```typescript
229
- import { getCurrentUserInfo, AuthClient } from 'ai-world-sdk';
230
-
231
- // 方式1: 使用便捷函数(推荐)
232
- const userInfo = await getCurrentUserInfo();
233
- console.log('用户信息:', userInfo);
234
- console.log('用户ID:', userInfo.id);
235
- console.log('用户名:', userInfo.full_name);
236
- console.log('邮箱:', userInfo.email);
237
-
238
- // 方式2: 使用 AuthClient 类
239
- const authClient = new AuthClient({
240
- baseUrl: 'http://localhost:8000', // 可选,默认使用全局配置
241
- token: 'your-token', // 可选,默认使用全局配置
242
- });
243
-
244
- const userInfo2 = await authClient.getCurrentUserInfo();
245
- console.log('用户信息:', userInfo2);
246
- ```
247
-
248
- ### 6. 下载代理
249
-
250
- ```typescript
251
- import { DownloadClient } from 'ai-world-sdk';
252
-
253
- const downloadClient = new DownloadClient({});
254
-
255
- // 普通下载(返回 Blob)
256
- const blob = await downloadClient.download({
257
- url: 'https://example.com/file.zip',
258
- filename: 'myfile.zip', // 可选
259
- });
260
- console.log('文件大小:', blob.size, '字节');
261
-
262
- // 下载并保存到本地
263
- await downloadClient.downloadAsFile({
264
- url: 'https://example.com/file.zip',
265
- filename: 'myfile.zip',
266
- });
267
-
268
- // 流式下载(使用 for await 迭代)
269
- let totalSize = 0;
270
- for await (const chunk of downloadClient.streamDownload({
271
- url: 'https://example.com/large-file.zip',
272
- filename: 'large-file.zip',
273
- })) {
274
- totalSize += chunk.length;
275
- console.log(`已下载: ${totalSize} 字节`);
276
- }
277
- console.log('下载完成,总大小:', totalSize, '字节');
278
- ```
279
-
280
- ## API 参考
281
-
282
- ### 聊天模型
283
-
284
- #### 支持的模型类
285
-
286
- | 模型类 | 说明 | 示例模型 |
287
- |--------|------|----------|
288
- | `ChatOpenAI` | OpenAI 兼容(GPT、O1、Doubao) | `gpt-4o-mini`, `doubao-pro-4k` |
289
- | `ChatGoogleGenerativeAI` | Google Gemini | `gemini-2.5-flash-image` |
290
- | `ChatAnthropic` | Anthropic Claude | `claude-3-sonnet-20240229` |
291
-
292
- #### 核心方法
293
-
294
- ```typescript
295
- // 非流式调用
296
- const response = await model.invoke([new HumanMessage('Hello')]);
297
-
298
- // 流式调用
299
- for await (const chunk of model.stream([new HumanMessage('Hello')])) {
300
- console.log(chunk.content);
301
- }
302
-
303
- // 批量处理
304
- const responses = await model.batch([
305
- [new HumanMessage('Question 1')],
306
- [new HumanMessage('Question 2')],
307
- ]);
308
-
309
- // 绑定参数
310
- const boundModel = model.bind({ temperature: 0.9, maxTokens: 1000 });
311
-
312
- // 绑定工具
313
- const modelWithTools = model.bindTools([...tools]);
314
- ```
315
-
316
- #### 工厂函数
317
-
318
- ```typescript
319
- import { createChatModel } from 'ai-world-sdk';
320
-
321
- // 根据模型名称自动选择正确的类
322
- const model = createChatModel('gemini-2.5-flash-image', {
323
- temperature: 0.7,
324
- provider: 'gemini', // 或 'api2img', 'doubao'
325
- });
326
- ```
327
-
328
- **支持的模型前缀:**
329
- - `gpt-*`, `o1-*` → `ChatOpenAI`
330
- - `doubao-*` → `ChatOpenAI`
331
- - `gemini-*` → `ChatGoogleGenerativeAI`
332
- - `claude-*` → `ChatAnthropic`
333
-
334
- **Provider 参数说明:**
335
- - `provider: 'api2img'` - 使用 api2img 聚合服务(推荐,支持所有模型)
336
- - `provider: 'gemini'` - 直接使用 Google Gemini API
337
- - `provider: 'doubao'` - 使用豆包服务
338
-
339
- **结构化输出参数:**
340
- - `jsonSchema?: Record<string, any>` - JSON Schema 定义,用于结构化输出(使用 `with_structured_output`)
341
-
342
- **推理模式参数:**
343
- - `reasoning?: object` - 推理配置,不同模型配置不同:
344
- - **OpenAI (o1, gpt-5 系列)**: `{ effort: 'low' | 'medium' | 'high', summary?: 'detailed' | 'auto' }`
345
- - **Gemini**: `{ thinking_level: 'low' | 'high' }`
346
- - **Claude**: `{ type: 'enabled', budget_tokens: number }`
347
-
348
- **联网搜索参数:**
349
- - `webSearch?: boolean` - 若模型支持联网搜索,设为 `true` 时会在请求中自动注入对应工具(Gemini 使用 `google_search`,OpenAI 兼容模型使用 `web_search`),模型可基于实时网络信息回答。
350
-
351
- ### 图像生成
352
-
353
- #### DoubaoImageGenerationClient
354
-
355
- ```typescript
356
- const client = new DoubaoImageGenerationClient({});
357
-
358
- const result = await client.generate({
359
- prompt: 'A beautiful landscape', // 必需
360
- model: 'doubao-seedream-4-5-251128', // 可选,默认值
361
- size: '2K', // 可选: 像素值(2048x2048, 2560x1440等)或K值(1K, 2K, 4K)
362
- quality: 'hd', // 可选: standard, hd
363
- n: 1, // 可选: 1-10
364
- response_format: 'url', // 可选: url, b64_json
365
- style: 'vivid', // 可选: vivid, natural
366
- watermark: false, // 可选
367
- });
368
- ```
369
-
370
- #### GeminiImageGenerationClient
371
-
372
- ```typescript
373
- const client = new GeminiImageGenerationClient({});
374
-
375
- // 基础用法(使用 Gemini 2.5 Flash - 快速模型)
376
- const result = await client.generate({
377
- prompt: 'A beautiful landscape', // 必需
378
- model: 'gemini-2.5-flash-image', // 推荐:快速、高效
379
- aspect_ratio: '16:9', // 可选: 1:1, 2:3, 3:2, 3:4, 4:3, 4:5, 5:4, 9:16, 16:9, 21:9
380
- });
381
-
382
- // 高级用法(使用 Gemini 3 Pro - 专业模型,支持高分辨率)
383
- const result2 = await client.generate({
384
- prompt: 'A futuristic city at sunset',
385
- model: 'gemini-3-pro-image-preview', // 专业级模型
386
- aspect_ratio: '16:9',
387
- image_size: '2K', // 可选: 1K, 2K, 4K(仅适用于 gemini-3-pro-image-preview)
388
- response_modalities: ['IMAGE'], // 仅返回图片,不返回文本
389
- temperature: 0.7, // 可选: 0.0-2.0
390
- max_output_tokens: 1000, // 可选
391
- });
392
-
393
- // 使用 api2img provider(通过 api2img 代理服务)
394
- const api2imgClient = new GeminiImageGenerationClient({
395
- provider: 'api2img', // 使用 api2img 代理
396
- });
397
-
398
- const result3 = await api2imgClient.generate({
399
- prompt: 'A beautiful landscape with mountains',
400
- model: 'gemini-3-pro-image-preview',
401
- aspect_ratio: '16:9',
402
- image_size: '1K',
403
- response_modalities: ['IMAGE'],
404
- });
405
-
406
- // 单图输入(文本 + 单张图片,实现编辑效果)
407
- const editResult = await client.generate({
408
- prompt: 'Add a small wizard hat on the cat\'s head',
409
- image: 'data:image/png;base64,iVBORw0KGgo...', // base64 编码的图片数据或 data URL
410
- model: 'gemini-2.5-flash-image',
411
- aspect_ratio: '1:1',
412
- response_modalities: ['IMAGE'],
413
- });
414
-
415
- // 多轮图片修改(迭代式优化图片)
416
- // 第一轮:创建初始图片
417
- const firstResponse = await client.chat({
418
- message: 'Create a vibrant infographic about photosynthesis',
419
- model: 'gemini-3-pro-image-preview',
420
- aspect_ratio: '16:9',
421
- response_modalities: ['TEXT', 'IMAGE'],
422
- });
423
-
424
- // 后续轮次:修改图片(使用返回的 chat_id)
425
- const secondResponse = await client.chat({
426
- chat_id: firstResponse.chat_id,
427
- message: 'Update this infographic to be in Spanish',
428
- model: 'gemini-3-pro-image-preview',
429
- aspect_ratio: '16:9',
430
- image_size: '2K',
431
- response_modalities: ['TEXT', 'IMAGE'],
432
- });
433
- ```
434
-
435
- **参数说明:**
436
-
437
- | 参数 | 类型 | 说明 | 默认值 |
438
- |------|------|------|--------|
439
- | `prompt` | `string` | 图像生成提示词(必需) | - |
440
- | `model` | `string` | 模型名称 | `gemini-2.0-flash-exp-image-generation` |
441
- | `image` | `string \| string[]` | 输入图片(base64 或 data URL)。可以是单个图片或图片数组(多图输入) | - |
442
- | `aspect_ratio` | `string` | 宽高比 | - |
443
- | `image_size` | `string` | 图片大小(仅 gemini-3-pro-image-preview) | - |
444
- | `response_modalities` | `array` | 响应模态 | `['TEXT', 'IMAGE']` |
445
- | `temperature` | `number` | 温度参数 | `0.7` |
446
- | `max_output_tokens` | `number` | 最大输出 token 数 | `1000` |
447
-
448
- **多图输入限制:**
449
- - `gemini-2.5-flash-image`: 最多支持 3 张输入图片
450
- - `gemini-3-pro-image-preview`: 最多支持 14 张输入图片(其中最多 5 张高保真图片)
451
-
452
- **支持的宽高比:** `1:1`, `2:3`, `3:2`, `3:4`, `4:3`, `4:5`, `5:4`, `9:16`, `16:9`, `21:9`
453
-
454
- **Provider 说明:**
455
-
456
- - `provider: 'gemini'`(默认)- 直接使用 Google Gemini 官方 API
457
- - `provider: 'api2img'` - 通过 api2img 代理服务调用,适合需要统一管理多个 API 的场景
458
-
459
- **模型对比:**
460
-
461
- | 模型 | 分辨率 | 特点 | 适用场景 |
462
- |------|--------|------|----------|
463
- | `gemini-2.5-flash-image` | 1024px | 快速、高效、成本低 | 日常使用、批量生成 |
464
- | `gemini-3-pro-image-preview` | 1K/2K/4K | 专业级、高分辨率、高级功能 | 专业设计、高分辨率需求 |
465
-
466
- **多轮图片修改:**
467
-
468
- - **`chat()`** - 多轮图片修改:通过对话迭代式优化图片
469
- - 首次调用创建新的聊天会话,返回 `chat_id`
470
- - 后续调用使用 `chat_id` 继续对话
471
- - 推荐使用 `gemini-3-pro-image-preview` 模型进行多轮编辑
472
-
473
- ### 视频生成
474
-
475
- #### VideoGenerationClient(豆包 Seedance)
476
-
477
- ```typescript
478
- const client = new VideoGenerationClient({});
479
-
480
- // 创建任务
481
- const task = await client.create({
482
- prompt: 'A beautiful sunset', // 或 image_url
483
- model: 'doubao-seedance-1-0-pro-fast-251015', // 可选
484
- duration: 5, // 可选: 1-10 秒
485
- aspect_ratio: '16:9', // 可选: 16:9, 9:16, 1:1
486
- resolution: '720p', // 可选
487
- return_last_frame: true, // 可选
488
- });
489
-
490
- // 查询状态
491
- const status = await client.get(task.id);
492
-
493
- // 轮询直到完成
494
- const result = await client.poll(task.id, {
495
- interval: 3000, // 轮询间隔(毫秒)
496
- timeout: 300000, // 超时时间(毫秒)
497
- });
498
- ```
499
-
500
- #### OpenAIVideoGenerationClient(OpenAI Sora)
501
-
502
- ```typescript
503
- const client = new OpenAIVideoGenerationClient({});
504
-
505
- // 文本生成视频
506
- const task = await client.generate({
507
- prompt: 'A beautiful sunset',
508
- model: 'sora-2', // 可选: sora-2, sora-2-pro
509
- provider: 'openai', // 可选: openai, api2img
510
- seconds: '4', // 可选: 4, 8, 12
511
- size: '1280x720', // 可选: 720x1280, 1280x720, 1024x1792, 1792x1024
512
- });
513
-
514
- // 图像生成视频
515
- const taskFromImage = await client.generate({
516
- prompt: 'Animate this scene',
517
- input_reference: 'data:image/png;base64,iVBORw0KGgo...', // Base64 或 URL
518
- model: 'sora-2',
519
- seconds: '8',
520
- });
521
-
522
- // 查询状态
523
- const status = await client.getTask(task.id);
524
-
525
- // 轮询直到完成
526
- const result = await client.waitForCompletion(task.id, {
527
- maxAttempts: 60,
528
- interval: 5000,
529
- onProgress: (status) => {
530
- console.log('状态:', status.status);
531
- }
532
- });
533
-
534
- // 下载视频
535
- const videoBlob = await client.downloadVideo(task.id, {
536
- variant: 'video' // 或 'thumbnail'
537
- });
538
-
539
- // 一键生成并等待
540
- const finalResult = await client.generateAndWait({
541
- prompt: 'A futuristic city',
542
- model: 'sora-2',
543
- seconds: '4'
544
- });
545
- ```
546
-
547
- ### 下载代理
548
-
549
- #### DownloadClient
550
-
551
- ```typescript
552
- const client = new DownloadClient({
553
- baseUrl: 'https://your-api.com', // 可选,默认使用全局配置
554
- token: 'your-token', // 可选,默认使用全局配置
555
- headers: { // 可选,自定义请求头
556
- 'X-Custom-Header': 'value',
557
- },
558
- });
559
- ```
560
-
561
- #### 方法
562
-
563
- ##### `download(options: DownloadOptions): Promise<Blob>`
564
-
565
- 普通下载文件,返回 Blob 对象。
566
-
567
- ```typescript
568
- const blob = await client.download({
569
- url: 'https://example.com/file.zip',
570
- filename: 'myfile.zip', // 可选,下载时的文件名
571
- });
572
-
573
- // 使用 Blob
574
- const text = await blob.text(); // 读取为文本
575
- const arrayBuffer = await blob.arrayBuffer(); // 读取为 ArrayBuffer
576
- const url = URL.createObjectURL(blob); // 创建对象 URL
577
- ```
578
-
579
- **参数:**
580
- - `url` (string, 必需): 要下载的文件 URL(必须是 http:// 或 https://)
581
- - `filename` (string, 可选): 下载时的文件名,不提供则从 URL 或响应头中提取
582
-
583
- **返回:** `Promise<Blob>` - 文件的 Blob 对象
584
-
585
- **错误处理:**
586
- ```typescript
587
- try {
588
- const blob = await client.download({
589
- url: 'https://example.com/file.zip',
590
- });
591
- console.log('下载成功:', blob.size, '字节');
592
- } catch (error) {
593
- if (error instanceof Error) {
594
- console.error('下载失败:', error.message);
595
- // 常见错误:
596
- // - "URL is required" - URL 参数缺失
597
- // - "Download failed: HTTP 404" - 文件不存在
598
- // - "Download failed: HTTP 403" - 访问被拒绝
599
- // - "下载超时,请稍后重试" - 下载超时
600
- }
601
- }
602
- ```
603
-
604
- ##### `downloadAsFile(options: DownloadOptions, downloadFilename?: string): Promise<void>`
605
-
606
- 下载文件并触发浏览器保存对话框。
607
-
608
- ```typescript
609
- await client.downloadAsFile({
610
- url: 'https://example.com/file.zip',
611
- filename: 'myfile.zip',
612
- }, 'custom-filename.zip'); // 可选,覆盖 filename
613
- ```
614
-
615
- **参数:**
616
- - `options`: 同 `download()` 方法
617
- - `downloadFilename` (string, 可选): 下载时的文件名,会覆盖 `options.filename`
618
-
619
- **返回:** `Promise<void>`
620
-
621
- ##### `streamDownload(options: StreamDownloadOptions): AsyncGenerator<Uint8Array>`
622
-
623
- 流式下载文件,返回异步迭代器,支持 `for await` 迭代。
624
-
625
- ```typescript
626
- let totalSize = 0;
627
- for await (const chunk of client.streamDownload({
628
- url: 'https://example.com/large-file.zip',
629
- filename: 'large-file.zip',
630
- })) {
631
- totalSize += chunk.length;
632
- console.log(`已下载: ${totalSize} 字节`);
633
- // 可以在这里处理每个数据块(例如:实时处理、显示进度等)
634
- }
635
- console.log('下载完成,总大小:', totalSize, '字节');
636
- ```
637
-
638
- **参数:**
639
- - `url` (string, 必需): 要下载的文件 URL
640
- - `filename` (string, 可选): 下载时的文件名
641
-
642
- **返回:** `AsyncGenerator<Uint8Array>` - 异步迭代器,每次迭代返回一个 `Uint8Array` 数据块
643
-
644
- **使用场景:**
645
- - 下载大文件时显示实时进度(通过累计 chunk.length)
646
- - 需要处理数据流(例如:实时解析、转码等)
647
- - 需要监控下载状态
648
- - 需要流式处理文件内容
649
-
650
- **示例:带进度显示**
651
-
652
- ```typescript
653
- // 如果服务器提供了 Content-Length,可以从响应头获取总大小
654
- let totalSize = 0;
655
- const total = 1024 * 1024 * 10; // 假设已知总大小(实际应从响应头获取)
656
-
657
- for await (const chunk of client.streamDownload({
658
- url: 'https://example.com/large-file.zip',
659
- })) {
660
- totalSize += chunk.length;
661
- const percent = total ? Math.round((totalSize / total) * 100) : null;
662
- console.log(`下载进度: ${totalSize}/${total || '未知'} (${percent || '?'}%)`);
663
- }
664
- ```
665
-
666
- **示例:流式处理并保存**
667
-
668
- ```typescript
669
- // 流式下载并实时保存到文件系统(Node.js 环境)
670
- import { createWriteStream } from 'fs';
671
- import { pipeline } from 'stream/promises';
672
-
673
- const chunks: Uint8Array[] = [];
674
- let totalSize = 0;
675
-
676
- for await (const chunk of client.streamDownload({
677
- url: 'https://example.com/large-file.zip',
678
- filename: 'large-file.zip',
679
- })) {
680
- chunks.push(chunk);
681
- totalSize += chunk.length;
682
- console.log(`已接收: ${totalSize} 字节`);
683
- }
684
-
685
- // 合并所有块并保存
686
- const blob = new Blob(chunks);
687
- const buffer = Buffer.from(await blob.arrayBuffer());
688
- await fs.promises.writeFile('large-file.zip', buffer);
689
- console.log('文件保存完成');
690
- ```
691
-
692
- **注意事项:**
693
- - 流式下载适合大文件,可以实时显示进度
694
- - 普通下载适合小文件,会一次性加载到内存
695
- - URL 必须是 `http://` 或 `https://` 协议
696
- - 文件名会自动从 URL 或响应头中提取(如果未提供)
697
- - 流式下载时,数据块大小由服务器决定,通常为 8KB-64KB
698
-
699
- ### 全局配置
700
-
701
- ```typescript
702
- import { sdkConfig } from 'ai-world-sdk';
703
-
704
- // 设置配置
705
- sdkConfig.setBaseUrl('your-base-url');
706
- sdkConfig.setToken('your-jwt-token');
707
- sdkConfig.setHeaders({ 'X-Custom-Header': 'value' });
708
- sdkConfig.setDebug(true);
709
-
710
- // 获取配置
711
- const baseUrl = sdkConfig.getServerUrl();
712
- const token = sdkConfig.getToken();
713
- const headers = sdkConfig.getHeaders();
714
- const debug = sdkConfig.getDebug();
715
-
716
- // 重置配置
717
- sdkConfig.reset();
718
- ```
719
-
720
- **浏览器环境自动配置:**
721
- - `baseUrl`: 从 `window.location.origin` 自动获取
722
- - `token`: 从 `document.cookie` 中的 `auth_token` 自动获取
723
-
724
- ### 消息类型
725
-
726
- ```typescript
727
- import { HumanMessage, SystemMessage, AIMessage, AIMessageChunk } from 'ai-world-sdk';
728
-
729
- // 文本消息
730
- const userMsg = new HumanMessage('Hello');
731
- const systemMsg = new SystemMessage('You are a helpful assistant.');
732
-
733
- // 多模态消息(文本 + 图像)
734
- const multimodalMsg = new HumanMessage([
735
- { type: 'text', text: 'Describe this image' },
736
- { type: 'image_url', image_url: 'data:image/jpeg;base64,...' },
737
- ]);
738
-
739
- // 音频消息(需要模型支持音频输入,如 Gemini)
740
- const audioMsg = new HumanMessage([
741
- { type: 'text', text: '这段音频说了什么?' },
742
- { type: 'audio', base64: '<base64 encoded audio data>', mime_type: 'audio/wav' },
743
- ]);
744
-
745
- // 音频消息(URL 方式)
746
- const audioUrlMsg = new HumanMessage([
747
- { type: 'text', text: '请描述这段音频' },
748
- { type: 'audio', url: 'https://example.com/audio.wav', mime_type: 'audio/wav' },
749
- ]);
750
-
751
- // 视频消息(需要模型支持视频输入,如 Gemini)
752
- const videoMsg = new HumanMessage([
753
- { type: 'text', text: '这段视频里发生了什么?' },
754
- { type: 'video', base64: '<base64 encoded video data>', mime_type: 'video/mp4' },
755
- ]);
756
-
757
- // 视频消息(URL 方式)
758
- const videoUrlMsg = new HumanMessage([
759
- { type: 'text', text: '请描述这段视频' },
760
- { type: 'video', url: 'https://example.com/video.mp4', mime_type: 'video/mp4' },
761
- ]);
762
-
763
- // AIMessageChunk 属性
764
- // - text: 获取文本内容(自动处理 string 或 MessageContent[] 类型)
765
- // - reasoning: 获取推理/思考内容(如果模型支持)
766
- // - content: 原始内容
767
- ```
768
-
769
- **音频/视频消息说明:**
770
- - `type`: `"audio"` 或 `"video"`
771
- - `base64`: base64 编码的媒体数据(与 `url` 二选一)
772
- - `url`: 媒体文件的 URL(与 `base64` 二选一)
773
- - `mime_type`: MIME 类型,使用 `base64` 时必填。常见值:
774
- - 音频:`audio/wav`, `audio/mp3`, `audio/ogg`, `audio/flac`, `audio/aac`
775
- - 视频:`video/mp4`, `video/webm`, `video/mpeg`
776
- - 音频输入支持:Gemini 模型、OpenAI(通过 `input_audio` 格式,需要模型支持)
777
- - 视频输入支持:Gemini 模型(OpenAI 暂不支持视频输入)
778
-
779
- ## Provider 调用示例
780
-
781
- SDK 支持多个 provider,每个 provider 对应不同的服务提供商。以下是各 provider 的使用示例:
782
-
783
- ### api2img Provider
784
-
785
- `api2img` 是一个多模型聚合服务,支持多种模型(OpenAI、Gemini、Claude 等)。
786
-
787
- ```typescript
788
- import { ChatOpenAI, ChatGoogleGenerativeAI, ChatAnthropic, HumanMessage } from 'ai-world-sdk';
789
-
790
- // OpenAI 模型(通过 api2img)
791
- const gptModel = new ChatOpenAI({
792
- modelName: 'gpt-4o-mini',
793
- temperature: 0.7,
794
- provider: 'api2img',
795
- });
796
-
797
- // Gemini 模型(通过 api2img)
798
- const geminiModel = new ChatGoogleGenerativeAI({
799
- modelName: 'gemini-2.5-flash',
800
- temperature: 0.7,
801
- provider: 'api2img',
802
- });
803
-
804
- // Gemini 图像生成(通过 api2img)
805
- import { GeminiImageGenerationClient } from 'ai-world-sdk';
806
-
807
- const geminiImageClient = new GeminiImageGenerationClient({
808
- provider: 'api2img',
809
- });
810
-
811
- const imageResult = await geminiImageClient.generate({
812
- prompt: 'A beautiful landscape',
813
- model: 'gemini-3-pro-image-preview',
814
- aspect_ratio: '16:9',
815
- image_size: '1K',
816
- response_modalities: ['IMAGE'],
817
- });
818
-
819
- // Claude 模型(通过 api2img)
820
- const claudeModel = new ChatAnthropic({
821
- modelName: 'claude-3-sonnet-20240229',
822
- temperature: 0.7,
823
- provider: 'api2img',
824
- });
825
-
826
- // 使用示例
827
- const response = await gptModel.invoke([
828
- new HumanMessage('Hello!'),
829
- ]);
830
- ```
831
-
832
- ### gemini Provider
833
-
834
- 直接使用 Google Gemini 官方 API。
835
-
836
- ```typescript
837
- import { ChatGoogleGenerativeAI, HumanMessage } from 'ai-world-sdk';
838
-
839
- const model = new ChatGoogleGenerativeAI({
840
- modelName: 'gemini-2.5-flash-image',
841
- temperature: 0.7,
842
- provider: 'gemini',
843
- });
844
-
845
- const response = await model.invoke([
846
- new HumanMessage('What is AI?'),
847
- ]);
848
- ```
849
-
850
- ### doubao Provider
851
-
852
- 使用豆包(字节跳动)的模型服务。
853
-
854
- ```typescript
855
- import { ChatOpenAI, HumanMessage } from 'ai-world-sdk';
856
-
857
- // Doubao 模型使用 ChatOpenAI(因为与 OpenAI 兼容)
858
- const doubaoModel = new ChatOpenAI({
859
- modelName: 'doubao-pro-4k',
860
- temperature: 0.7,
861
- provider: 'doubao',
862
- });
863
-
864
- const response = await doubaoModel.invoke([
865
- new HumanMessage('你好!'),
866
- ]);
867
- ```
868
-
869
- ### Provider 选择指南
870
-
871
- | Provider | 适用场景 | 支持的模型 |
872
- |----------|----------|------------|
873
- | `gemini` | 直接使用 Google Gemini API | 所有 Gemini 模型 |
874
- | `api2img` | 使用 api2img 聚合服务 | 所有模型 |
875
- | `doubao` | 使用豆包服务 | Doubao 系列模型 |
876
-
877
- **推荐使用 `api2img` provider**,因为它提供了统一的接口和更好的模型选择灵活性。
878
-
879
- ## 完整示例
880
-
881
- ### 聊天对话
882
-
883
- ```typescript
884
- import { ChatGoogleGenerativeAI, HumanMessage, SystemMessage } from 'ai-world-sdk';
885
-
886
- const model = new ChatGoogleGenerativeAI({
887
- modelName: 'gemini-2.5-flash-image',
888
- temperature: 0.7,
889
- provider: 'gemini',
890
- });
891
-
892
- // 简单对话
893
- const response = await model.invoke([
894
- new HumanMessage('What is AI?'),
895
- ]);
896
- console.log(response.content);
897
-
898
- // 带系统提示的对话
899
- const response2 = await model.invoke([
900
- new SystemMessage('You are a helpful assistant.'),
901
- new HumanMessage('Explain machine learning.'),
902
- ]);
903
- ```
904
-
905
- ### 推理模式(Reasoning)
906
-
907
- 推理模式允许模型在生成响应时展示其思考过程。不同的模型提供商有不同的推理配置方式。
908
-
909
- #### OpenAI 推理模式(o1、gpt-5 系列)
910
-
911
- ```typescript
912
- import { ChatOpenAI, HumanMessage, AIMessageChunk } from 'ai-world-sdk';
913
-
914
- const model = new ChatOpenAI({
915
- modelName: 'gpt-5.2',
916
- temperature: 0.7,
917
- provider: 'api2img',
918
- reasoning: {
919
- effort: 'high', // 'low' | 'medium' | 'high'
920
- summary: 'detailed', // 'detailed' | 'auto'(可选)
921
- },
922
- });
923
-
924
- // 流式调用获取推理过程
925
- let fullText = '';
926
- let reasoningText = '';
927
- for await (const chunk of model.stream([
928
- new HumanMessage('解释量子纠缠原理'),
929
- ])) {
930
- fullText += chunk.content || '';
931
- reasoningText += chunk.reasoning || ''; // 获取推理内容
932
- }
933
-
934
- console.log('推理过程:', reasoningText);
935
- console.log('最终回复:', fullText);
936
- ```
937
-
938
- #### Google Gemini 推理模式
939
-
940
- ```typescript
941
- import { ChatGoogleGenerativeAI, HumanMessage } from 'ai-world-sdk';
942
-
943
- const model = new ChatGoogleGenerativeAI({
944
- modelName: 'gemini-3-pro-preview',
945
- temperature: 0.7,
946
- provider: 'gemini',
947
- reasoning: {
948
- thinking_level: 'high', // 'low' | 'high'
949
- },
950
- });
951
-
952
- // 流式调用获取思考过程
953
- for await (const chunk of model.stream([
954
- new HumanMessage('分析这个数学问题'),
955
- ])) {
956
- console.log('内容:', chunk.content);
957
- console.log('思考:', chunk.reasoning); // 获取思考内容
958
- }
959
- ```
960
-
961
- #### Anthropic Claude 推理模式(Extended Thinking)
962
-
963
- ```typescript
964
- import { ChatAnthropic, HumanMessage } from 'ai-world-sdk';
965
-
966
- const model = new ChatAnthropic({
967
- modelName: 'claude-3-5-sonnet-20241022',
968
- temperature: 0.7,
969
- provider: 'api2img',
970
- reasoning: {
971
- type: 'enabled',
972
- budget_tokens: 5000, // 思考预算(token 数量)
973
- },
974
- });
975
-
976
- // 流式调用获取思考过程
977
- for await (const chunk of model.stream([
978
- new HumanMessage('解决这个复杂问题'),
979
- ])) {
980
- console.log('内容:', chunk.content);
981
- console.log('思考:', chunk.reasoning);
982
- }
983
- ```
984
-
985
- **推理参数说明:**
986
-
987
- | 模型类型 | 参数 | 说明 |
988
- |---------|------|------|
989
- | OpenAI (o1, gpt-5) | `effort: 'low' \| 'medium' \| 'high'` | 推理努力程度 |
990
- | OpenAI (o1, gpt-5) | `summary: 'detailed' \| 'auto'` | 推理摘要模式(可选) |
991
- | Gemini | `thinking_level: 'low' \| 'high'` | 思考深度级别 |
992
- | Claude | `type: 'enabled'` | 启用扩展思考 |
993
- | Claude | `budget_tokens: number` | 思考预算(建议 2000-10000) |
994
-
995
- **获取推理内容:**
996
-
997
- 在流式调用中,可以通过 `AIMessageChunk.reasoning` 属性获取模型的推理/思考内容:
998
-
999
- ```typescript
1000
- for await (const chunk of model.stream([...])) {
1001
- // chunk.content - 最终响应内容
1002
- // chunk.reasoning - 推理/思考过程(如果模型支持)
1003
- }
1004
- ```
1005
-
1006
- ### 结构化输出(JSON Schema)
1007
-
1008
- 使用 `jsonSchema` 参数可以让模型返回结构化的 JSON 数据,而不是自由文本。
1009
-
1010
- ```typescript
1011
- import { ChatOpenAI, ChatGoogleGenerativeAI, HumanMessage, createChatModel } from 'ai-world-sdk';
1012
-
1013
- // 使用 ChatOpenAI 进行结构化输出
1014
- const openaiModel = new ChatOpenAI({
1015
- modelName: 'gpt-4o-mini',
1016
- temperature: 0.7,
1017
- provider: 'api2img',
1018
- jsonSchema: {
1019
- type: 'object',
1020
- properties: {
1021
- name: { type: 'string', description: '用户姓名' },
1022
- age: { type: 'integer', description: '用户年龄' },
1023
- email: { type: 'string', description: '用户邮箱' },
1024
- },
1025
- required: ['name', 'age'],
1026
- },
1027
- });
1028
-
1029
- const response = await openaiModel.invoke([
1030
- new HumanMessage('请提取以下信息:张三,25岁,邮箱是zhangsan@example.com'),
1031
- ]);
1032
-
1033
- // 响应内容将是结构化的 JSON 对象
1034
- console.log(response.content); // { name: '张三', age: 25, email: 'zhangsan@example.com' }
1035
- ```
1036
-
1037
- **使用 Gemini 模型的结构化输出:**
1038
-
1039
- ```typescript
1040
- const geminiModel = new ChatGoogleGenerativeAI({
1041
- modelName: 'gemini-2.5-flash',
1042
- temperature: 0.7,
1043
- provider: 'gemini',
1044
- jsonSchema: {
1045
- type: 'object',
1046
- properties: {
1047
- summary: { type: 'string', description: '摘要' },
1048
- keywords: {
1049
- type: 'array',
1050
- items: { type: 'string' },
1051
- description: '关键词列表',
1052
- },
1053
- sentiment: {
1054
- type: 'string',
1055
- enum: ['positive', 'neutral', 'negative'],
1056
- description: '情感倾向',
1057
- },
1058
- },
1059
- required: ['summary', 'keywords'],
1060
- },
1061
- });
1062
-
1063
- const response = await geminiModel.invoke([
1064
- new HumanMessage("分析这句话的情感:'今天天气真好,心情很愉快!'"),
1065
- ]);
1066
- ```
1067
-
1068
- **使用 createChatModel 工厂函数:**
1069
-
1070
- ```typescript
1071
- const model = createChatModel('gpt-4o-mini', {
1072
- temperature: 0.7,
1073
- provider: 'api2img',
1074
- jsonSchema: {
1075
- type: 'object',
1076
- properties: {
1077
- title: { type: 'string', description: '文章标题' },
1078
- content: { type: 'string', description: '文章内容' },
1079
- tags: {
1080
- type: 'array',
1081
- items: { type: 'string' },
1082
- description: '标签列表',
1083
- },
1084
- },
1085
- required: ['title', 'content'],
1086
- },
1087
- });
1088
-
1089
- const response = await model.invoke([
1090
- new HumanMessage('生成一篇关于人工智能的短文,包含标题、内容和标签'),
1091
- ]);
1092
- ```
1093
-
1094
- **注意事项:**
1095
- - `jsonSchema` 必须符合 [JSON Schema](https://json-schema.org/) 规范
1096
- - 对于 OpenAI 兼容的模型(如 GPT、Doubao),JSON Schema 会自动添加 `title` 和 `description`(如果缺失)
1097
- - 对于 Gemini 和 Anthropic 模型,直接使用提供的 JSON Schema
1098
- - 结构化输出的响应内容可能是 JSON 字符串或对象,需要根据实际情况解析
1099
- - 结构化输出使用 LangChain 的 `with_structured_output` 方法,底层通过 `method="json_schema"` 实现
1100
-
1101
- ### 流式响应
1102
-
1103
- ```typescript
1104
- let fullText = '';
1105
- for await (const chunk of model.stream([
1106
- new HumanMessage('Tell me a story about AI'),
1107
- ])) {
1108
- // 方式1: 使用 text 属性(推荐,自动处理 content 类型)
1109
- fullText += chunk.text;
1110
- process.stdout.write(chunk.text);
1111
-
1112
- // 方式2: 直接使用 content(需要判断类型)
1113
- // if (typeof chunk.content === 'string') {
1114
- // fullText += chunk.content;
1115
- // process.stdout.write(chunk.content);
1116
- // }
1117
- }
1118
- console.log('\n完整回复:', fullText);
1119
- ```
1120
-
1121
- **AIMessageChunk.text 属性说明:**
1122
-
1123
- `AIMessageChunk` 提供了便捷的 `text` 属性,可以自动提取文本内容:
1124
- - 如果 `content` 是字符串,直接返回该字符串
1125
- - 如果 `content` 是 `MessageContent[]`,提取所有 `type: "text"` 的内容并拼接
1126
- - 否则返回空字符串
1127
-
1128
- 这样可以简化流式调用中的文本处理,无需手动判断 `content` 类型。
1129
-
1130
- ### 工具调用
1131
-
1132
- ```typescript
1133
- import { ToolDefinition } from 'ai-world-sdk';
1134
-
1135
- const tools: ToolDefinition[] = [
1136
- {
1137
- type: 'function',
1138
- function: {
1139
- name: 'get_weather',
1140
- description: 'Get the current weather',
1141
- parameters: {
1142
- type: 'object',
1143
- properties: {
1144
- location: { type: 'string' },
1145
- },
1146
- required: ['location'],
1147
- },
1148
- },
1149
- },
1150
- ];
1151
-
1152
- const modelWithTools = model.bindTools(tools);
1153
- const response = await modelWithTools.invoke([
1154
- new HumanMessage('What is the weather in Paris?'),
1155
- ]);
1156
- ```
1157
-
1158
- ### 联网搜索(webSearch)
1159
-
1160
- 当模型支持联网搜索时,可通过 `webSearch: true` 启用,模型将能基于实时网络信息回答。
1161
-
1162
- ```typescript
1163
- import { createChatModel, HumanMessage } from 'ai-world-sdk';
1164
-
1165
- // Gemini 模型(使用 Google Search)
1166
- const geminiModel = createChatModel('gemini-2.0-flash-exp', {
1167
- provider: 'gemini',
1168
- webSearch: true,
1169
- });
1170
-
1171
- // OpenAI 兼容模型(使用 web_search 工具)
1172
- const openaiModel = createChatModel('gpt-4o-mini', {
1173
- provider: 'api2img',
1174
- webSearch: true,
1175
- });
1176
-
1177
- const response = await geminiModel.invoke([
1178
- new HumanMessage('今天北京天气如何?最近有什么科技新闻?'),
1179
- ]);
1180
- console.log(response.content);
1181
- ```
1182
-
1183
- **说明:**
1184
- - 启用后 SDK 会在请求中自动注入对应工具:Gemini 使用 `google_search`,OpenAI 兼容模型使用 `type: "web_search"`。
1185
- - 是否真正执行搜索取决于后端与模型是否支持;仅当模型支持联网搜索时才会生效。
1186
- - 可与 `bindTools` 同时使用,webSearch 注入的工具会与自定义工具一起传入。
1187
-
1188
- ### 图像生成工作流
1189
-
1190
- #### 豆包图像生成
1191
-
1192
- 豆包 Seedream 支持多种图像生成模式:
1193
-
1194
- **支持的尺寸选项:**
1195
-
1196
- - **像素值(宽x高)**:
1197
- - `2048x2048` (1:1 正方形)
1198
- - `2304x1728` (4:3 横屏)
1199
- - `1728x2304` (3:4 竖屏)
1200
- - `2560x1440` (16:9 横屏)
1201
- - `1440x2560` (9:16 竖屏)
1202
- - `2496x1664` (3:2 横屏)
1203
- - `1664x2496` (2:3 竖屏)
1204
- - `3024x1296` (21:9 超宽屏)
1205
-
1206
- - **K 值(根据模型版本)**:
1207
- - `1K` - 仅 4.0 版本支持
1208
- - `2K` - 4.0 和 4.5 版本支持
1209
- - `4K` - 4.0 和 4.5 版本支持
1210
-
1211
- **1. 文生图(文本生成图像)**
1212
-
1213
- ```typescript
1214
- import { DoubaoImageGenerationClient } from 'ai-world-sdk';
1215
-
1216
- const client = new DoubaoImageGenerationClient({});
1217
-
1218
- // 生成单张图像
1219
- const result = await client.generate({
1220
- prompt: 'A futuristic city skyline at sunset',
1221
- size: '2048x2048', // 1:1 正方形,或使用 '2K', '4K' 等
1222
- quality: 'hd',
1223
- });
1224
-
1225
- console.log('图像 URL:', result.data[0]?.url);
1226
- ```
1227
-
1228
- **2. 图文生图(单图输入单图输出)**
1229
-
1230
- 基于一张参考图片生成新图像:
1231
-
1232
- ```typescript
1233
- // 使用单张图片作为输入
1234
- const result = await client.generate({
1235
- prompt: '将这张图片转换为水彩画风格',
1236
- image: 'data:image/png;base64,iVBORw0KGgo...', // base64 编码的图片或 data URL
1237
- size: '2560x1440', // 16:9 横屏
1238
- quality: 'hd',
1239
- });
1240
-
1241
- console.log('生成的图像 URL:', result.data[0]?.url);
1242
- ```
1243
-
1244
- **3. 多图融合(多图输入单图输出)**
1245
-
1246
- 融合多张参考图片生成新图像:
1247
-
1248
- ```typescript
1249
- // 使用多张图片作为输入
1250
- const result = await client.generate({
1251
- prompt: '将图1的服装换为图2的服装风格',
1252
- image: [
1253
- 'data:image/png;base64,iVBORw0KGgo...', // 第一张图片
1254
- 'data:image/png;base64,iVBORw0KGgo...', // 第二张图片
1255
- ],
1256
- size: '2048x2048', // 1:1 正方形
1257
- quality: 'hd',
1258
- });
1259
-
1260
- console.log('融合后的图像 URL:', result.data[0]?.url);
1261
- ```
1262
-
1263
- **4. 组图输出(多图输出)**
1264
-
1265
- 一次生成多张不同风格的图像:
1266
-
1267
- ```typescript
1268
- // 生成多张图像(组图输出)
1269
- const multiResult = await client.generate({
1270
- prompt: 'A beautiful landscape',
1271
- n: 3, // 生成 3 张图像
1272
- size: '2560x1440', // 16:9 横屏
1273
- });
1274
-
1275
- multiResult.data.forEach((image, index) => {
1276
- console.log(`图像 ${index + 1}:`, image.url);
1277
- });
1278
- ```
1279
-
1280
- **组合使用示例**
1281
-
1282
- ```typescript
1283
- // 图文生图 + 组图输出:基于一张图片生成多张不同风格的图像
1284
- const result = await client.generate({
1285
- prompt: '生成不同风格的艺术作品',
1286
- image: 'data:image/png;base64,iVBORw0KGgo...',
1287
- n: 4, // 生成 4 张不同风格的图像
1288
- size: '2048x2048', // 1:1 正方形
1289
- quality: 'hd',
1290
- });
1291
- ```
1292
-
1293
- #### Gemini 图像生成
1294
-
1295
- ```typescript
1296
- import { GeminiImageGenerationClient } from 'ai-world-sdk';
1297
-
1298
- const client = new GeminiImageGenerationClient({});
1299
-
1300
- // 1. 文生图(仅文本提示)
1301
- const result = await client.generate({
1302
- prompt: 'A beautiful sunset over the ocean',
1303
- model: 'gemini-2.5-flash-image',
1304
- aspect_ratio: '16:9',
1305
- });
1306
-
1307
- console.log('图像 URL:', result.data[0]?.url || 'Base64 编码');
1308
- if (result.text) {
1309
- console.log('图像描述:', result.text);
1310
- }
1311
-
1312
- // 2. 单图输入(文本 + 单张图片)
1313
- const result2 = await client.generate({
1314
- prompt: 'Create a picture of my cat eating a nano-banana in a fancy restaurant',
1315
- image: 'data:image/png;base64,iVBORw0KGgo...', // base64 编码的图片或 data URL
1316
- model: 'gemini-2.5-flash-image',
1317
- aspect_ratio: '16:9',
1318
- });
1319
-
1320
- // 3. 多图输入(文本 + 多张图片)
1321
- // gemini-2.5-flash-image 最多支持 3 张图片
1322
- // gemini-3-pro-image-preview 最多支持 14 张图片
1323
- const result3 = await client.generate({
1324
- prompt: 'An office group photo of these people, they are making funny faces.',
1325
- image: [
1326
- 'data:image/png;base64,iVBORw0KGgo...', // 第一张图片
1327
- 'data:image/png;base64,iVBORw0KGgo...', // 第二张图片
1328
- 'data:image/png;base64,iVBORw0KGgo...', // 第三张图片
1329
- ],
1330
- model: 'gemini-3-pro-image-preview',
1331
- aspect_ratio: '5:4',
1332
- image_size: '2K',
1333
- response_modalities: ['IMAGE'],
1334
- });
1335
-
1336
- // 4. 使用 Gemini 3 Pro(专业模型,支持高分辨率)
1337
- const result4 = await client.generate({
1338
- prompt: 'A futuristic city at night',
1339
- model: 'gemini-3-pro-image-preview',
1340
- aspect_ratio: '21:9', // 超宽屏
1341
- image_size: '4K', // 4K 分辨率
1342
- response_modalities: ['IMAGE'], // 仅返回图片
1343
- });
1344
-
1345
- console.log('4K 图像:', result4.data[0]?.b64_json ? 'Base64 编码' : result4.data[0]?.url);
1346
- ```
1347
-
1348
- ### 用户认证工作流
1349
-
1350
- ```typescript
1351
- import { getCurrentUserInfo, AuthClient } from 'ai-world-sdk';
1352
-
1353
- // 1. 获取当前用户信息(使用便捷函数)
1354
- try {
1355
- const userInfo = await getCurrentUserInfo();
1356
- console.log('用户ID:', userInfo.id);
1357
- console.log('用户名:', userInfo.full_name);
1358
- console.log('邮箱:', userInfo.email);
1359
- console.log('是否超级用户:', userInfo.is_superuser);
1360
- } catch (error) {
1361
- console.error('获取用户信息失败:', error);
1362
- // 可能需要重新登录
1363
- }
1364
-
1365
- // 2. 使用 AuthClient 类(需要自定义配置时)
1366
- const authClient = new AuthClient({
1367
- baseUrl: 'http://localhost:8000',
1368
- token: 'your-jwt-token',
1369
- });
1370
-
1371
- const userInfo = await authClient.getCurrentUserInfo();
1372
-
1373
- // 3. 检查用户权限
1374
- if (userInfo.is_superuser) {
1375
- console.log('用户是超级管理员');
1376
- }
1377
-
1378
- if (userInfo.is_active) {
1379
- console.log('用户账户已激活');
1380
- }
1381
-
1382
- // 4. 显示用户信息
1383
- console.log(`欢迎, ${userInfo.full_name || userInfo.email || '用户'}`);
1384
- if (userInfo.avatar_url) {
1385
- console.log('头像:', userInfo.avatar_url);
1386
- }
1387
- ```
1388
-
1389
- ### 视频生成工作流
1390
-
1391
- #### 豆包视频生成(Doubao Seedance)
1392
-
1393
- ```typescript
1394
- import { VideoGenerationClient } from 'ai-world-sdk';
1395
-
1396
- const client = new VideoGenerationClient({});
1397
-
1398
- // 1. 创建任务
1399
- const task = await client.create({
1400
- prompt: 'A beautiful sunset over the ocean',
1401
- duration: 5,
1402
- aspect_ratio: '16:9',
1403
- resolution: '720p',
1404
- });
1405
-
1406
- // 2. 轮询直到完成
1407
- const result = await client.poll(task.id, {
1408
- interval: 3000,
1409
- timeout: 300000,
1410
- });
1411
-
1412
- if (result.status === 'succeeded') {
1413
- console.log('视频 URL:', result.content?.video_url);
1414
- if (result.content?.last_frame_url) {
1415
- console.log('最后一帧:', result.content.last_frame_url);
1416
- }
1417
- } else {
1418
- console.error('生成失败:', result.error?.message);
1419
- }
1420
- ```
1421
-
1422
- #### OpenAI 视频生成(Sora)
1423
-
1424
- ```typescript
1425
- import { OpenAIVideoGenerationClient } from 'ai-world-sdk';
1426
-
1427
- const client = new OpenAIVideoGenerationClient({});
1428
-
1429
- // 1. 文本生成视频
1430
- const task = await client.generate({
1431
- prompt: 'A serene mountain landscape with a flowing river',
1432
- model: 'sora-2', // 'sora-2' 或 'sora-2-pro'
1433
- provider: 'api2img', // 'api2img' 或 'api2img'
1434
- seconds: '4', // '4', '8', 或 '12'
1435
- size: '1280x720' // '720x1280', '1280x720', '1024x1792', '1792x1024'
1436
- });
1437
-
1438
- console.log('任务已创建:', task.id);
1439
- console.log('任务状态:', task.status);
1440
-
1441
- // 2. 查询任务状态
1442
- const status = await client.getTask(task.id, 'api2img');
1443
- console.log('当前状态:', status.status);
1444
-
1445
- // 3. 轮询等待完成
1446
- const result = await client.waitForCompletion(
1447
- task.id,
1448
- 'api2img', // provider 参数
1449
- {
1450
- maxAttempts: 60,
1451
- interval: 5000,
1452
- onProgress: (status) => {
1453
- console.log(`状态: ${status.status}`);
1454
- if (status.status === 'in_progress') {
1455
- console.log('正在生成...');
1456
- }
1457
- }
1458
- }
1459
- );
1460
-
1461
- if (result.status === 'completed') {
1462
- console.log('✅ 视频生成成功!');
1463
-
1464
- // 4. 流式下载视频
1465
- const videoBlob = await client.downloadVideo(
1466
- result.id,
1467
- 'api2img', // provider
1468
- 'video' // 'video' 或 'thumbnail'
1469
- );
1470
-
1471
- console.log('视频大小:', (videoBlob.size / 1024 / 1024).toFixed(2), 'MB');
1472
- console.log('视频类型:', videoBlob.type);
1473
-
1474
- // 在浏览器中创建下载链接
1475
- const url = URL.createObjectURL(videoBlob);
1476
- const a = document.createElement('a');
1477
- a.href = url;
1478
- a.download = `sora_video_${result.id}.mp4`;
1479
- a.click();
1480
- URL.revokeObjectURL(url);
1481
-
1482
- // 也可以下载缩略图
1483
- const thumbnail = await client.downloadVideo(
1484
- result.id,
1485
- 'api2img',
1486
- 'thumbnail'
1487
- );
1488
- console.log('缩略图大小:', (thumbnail.size / 1024).toFixed(2), 'KB');
1489
- } else if (result.status === 'failed') {
1490
- console.error('❌ 生成失败:', result.error);
1491
- }
1492
-
1493
- // 一键生成并等待(简化版)
1494
- try {
1495
- const result2 = await client.generateAndWait({
1496
- prompt: 'A futuristic city with flying cars at night',
1497
- model: 'sora-2',
1498
- provider: 'api2img',
1499
- seconds: '8',
1500
- size: '1280x720'
1501
- }, {
1502
- maxAttempts: 60,
1503
- interval: 5000,
1504
- onProgress: (status) => console.log('进度:', status.status)
1505
- });
1506
-
1507
- console.log('视频生成完成:', result2.id);
1508
-
1509
- // 流式下载
1510
- const video = await client.downloadVideo(
1511
- result2.id,
1512
- 'api2img',
1513
- 'video'
1514
- );
1515
- console.log('视频大小:', (video.size / 1024 / 1024).toFixed(2), 'MB');
1516
- } catch (error) {
1517
- console.error('视频生成失败:', error);
1518
- }
1519
-
1520
- // 图像生成视频示例
1521
- const imageToVideoTask = await client.generate({
1522
- prompt: 'Make this scene come alive with gentle movements',
1523
- input_reference: 'data:image/png;base64,iVBORw0KGgo...', // 图像 base64 或 URL
1524
- model: 'sora-2',
1525
- provider: 'api2img',
1526
- seconds: '4'
1527
- });
1528
-
1529
- const imageToVideoResult = await client.waitForCompletion(
1530
- imageToVideoTask.id,
1531
- 'api2img'
1532
- );
1533
-
1534
- if (imageToVideoResult.status === 'completed') {
1535
- console.log('图生视频完成:', imageToVideoResult.id);
1536
-
1537
- // 下载视频
1538
- const videoBlob = await client.downloadVideo(
1539
- imageToVideoResult.id,
1540
- 'api2img',
1541
- 'video'
1542
- );
1543
- console.log('视频已下载,大小:', videoBlob.size);
1544
- }
1545
- ```
1546
-
1547
- ### 用户认证工作流
1548
-
1549
- ```typescript
1550
- import { getCurrentUserInfo, AuthClient } from 'ai-world-sdk';
1551
-
1552
- // 1. 获取当前用户信息(使用便捷函数)
1553
- try {
1554
- const userInfo = await getCurrentUserInfo();
1555
- console.log('用户ID:', userInfo.id);
1556
- console.log('用户名:', userInfo.full_name);
1557
- console.log('邮箱:', userInfo.email);
1558
- console.log('是否超级用户:', userInfo.is_superuser);
1559
- } catch (error) {
1560
- console.error('获取用户信息失败:', error);
1561
- // 可能需要重新登录
1562
- }
1563
-
1564
- // 2. 使用 AuthClient 类(需要自定义配置时)
1565
- const authClient = new AuthClient({
1566
- baseUrl: 'http://localhost:8000',
1567
- token: 'your-jwt-token',
1568
- });
1569
-
1570
- const userInfo = await authClient.getCurrentUserInfo();
1571
-
1572
- // 3. 检查用户权限
1573
- if (userInfo.is_superuser) {
1574
- console.log('用户是超级管理员');
1575
- }
1576
-
1577
- if (userInfo.is_active) {
1578
- console.log('用户账户已激活');
1579
- }
1580
-
1581
- // 4. 显示用户信息
1582
- console.log(`欢迎, ${userInfo.full_name || userInfo.email || '用户'}`);
1583
- if (userInfo.avatar_url) {
1584
- console.log('头像:', userInfo.avatar_url);
1585
- }
1586
- ```
1587
-
1588
- ### 下载代理工作流
1589
-
1590
- ```typescript
1591
- import { DownloadClient } from 'ai-world-sdk';
1592
-
1593
- const client = new DownloadClient({});
1594
-
1595
- // 1. 普通下载(小文件)
1596
- const blob = await client.download({
1597
- url: 'https://example.com/small-file.json',
1598
- filename: 'data.json',
1599
- });
1600
-
1601
- // 读取文件内容
1602
- const text = await blob.text();
1603
- const data = JSON.parse(text);
1604
- console.log('下载的数据:', data);
1605
-
1606
- // 2. 下载并保存到本地
1607
- await client.downloadAsFile({
1608
- url: 'https://example.com/document.pdf',
1609
- filename: 'document.pdf',
1610
- });
1611
-
1612
- // 3. 流式下载大文件(带进度显示)
1613
- let totalSize = 0;
1614
- const total = 1024 * 1024 * 100; // 假设已知总大小(实际应从响应头获取)
1615
-
1616
- for await (const chunk of client.streamDownload({
1617
- url: 'https://example.com/large-video.mp4',
1618
- filename: 'video.mp4',
1619
- })) {
1620
- totalSize += chunk.length;
1621
-
1622
- // 显示进度
1623
- if (total) {
1624
- const percent = Math.round((totalSize / total) * 100);
1625
- console.log(`下载进度: ${percent}% (${totalSize}/${total} 字节)`);
1626
- } else {
1627
- console.log(`已下载: ${totalSize} 字节`);
1628
- }
1629
-
1630
- // 可以在这里处理每个数据块
1631
- // 例如:实时验证、显示下载速度等
1632
- }
1633
-
1634
- console.log(`下载完成!总大小: ${totalSize} 字节`);
1635
-
1636
- // 4. 批量下载多个文件
1637
- const urls = [
1638
- 'https://example.com/file1.zip',
1639
- 'https://example.com/file2.zip',
1640
- 'https://example.com/file3.zip',
1641
- ];
1642
-
1643
- for (const url of urls) {
1644
- try {
1645
- await client.downloadAsFile({
1646
- url,
1647
- filename: url.split('/').pop() || 'download',
1648
- });
1649
- console.log(`已下载: ${url}`);
1650
- } catch (error) {
1651
- console.error(`下载失败 ${url}:`, error);
1652
- }
1653
- }
1654
-
1655
- // 5. 流式下载并实时处理(例如:解析 JSON 流)
1656
- let buffer = '';
1657
- for await (const chunk of client.streamDownload({
1658
- url: 'https://example.com/large-data.jsonl',
1659
- })) {
1660
- // 将 Uint8Array 转换为字符串
1661
- buffer += new TextDecoder().decode(chunk);
1662
-
1663
- // 处理完整的行
1664
- const lines = buffer.split('\n');
1665
- buffer = lines.pop() || ''; // 保留不完整的行
1666
-
1667
- for (const line of lines) {
1668
- if (line.trim()) {
1669
- const data = JSON.parse(line);
1670
- console.log('处理数据:', data);
1671
- }
1672
- }
1673
- }
1674
- ```
1675
-
1676
- ## 支持的模型
1677
-
1678
- ### 聊天模型
1679
-
1680
- | 提供商 | Provider | 模型示例 | 模型类 | 支持推理 |
1681
- |--------|----------|----------|--------|---------|
1682
- | OpenAI | `api2img` | `gpt-4o-mini`, `gpt-4` | `ChatOpenAI` | ❌ |
1683
- | OpenAI | `api2img` | `o1-preview`, `o1-mini`, `gpt-5.2` | `ChatOpenAI` | ✅ |
1684
- | Google Gemini | `gemini` 或 `api2img` | `gemini-2.5-flash-image` | `ChatGoogleGenerativeAI` | ❌ |
1685
- | Google Gemini | `gemini` 或 `api2img` | `gemini-3-pro-preview` | `ChatGoogleGenerativeAI` | ✅ |
1686
- | Anthropic Claude | `api2img` | `claude-3-sonnet-20240229` | `ChatAnthropic` | ❌ |
1687
- | Anthropic Claude | `api2img` | `claude-3-5-sonnet-20241022` | `ChatAnthropic` | ✅ |
1688
- | Doubao | `doubao` 或 `api2img` | `doubao-pro-4k`, `doubao-seedream-4-5-251128` | `ChatOpenAI` | ❌ |
1689
-
1690
- **注意:**
1691
- - 使用 `api2img` 或 `api2img` provider 可以访问所有模型,推荐用于多模型场景
1692
- - 使用特定 provider(如 `gemini`、`doubao`)会直接调用对应的官方 API
1693
- - 支持推理的模型可以通过 `reasoning` 参数启用思考/推理功能
1694
-
1695
- ### 图像生成模型
1696
-
1697
- - **豆包 Seedream**:
1698
- - `doubao-seedream-4-5-251128` (4.5版本,默认) - 支持 2K、4K 和像素值尺寸
1699
- - `doubao-seedream-4-0` (4.0版本) - 支持 1K、2K、4K 和像素值尺寸
1700
- - **Google Gemini**:
1701
- - `gemini-2.5-flash-image` (Nano Banana) - **推荐**,快速、高效,1024px 分辨率,支持所有宽高比
1702
- - `gemini-3-pro-image-preview` (Nano Banana Pro) - 专业级,支持 1K/2K/4K 分辨率,支持 Google 搜索、思考模式,最多 14 张参考图片
1703
-
1704
- **模型选择建议:**
1705
- - **日常使用**: `gemini-2.5-flash-image` - 速度快,成本低
1706
- - **专业需求**: `gemini-3-pro-image-preview` - 高分辨率、高级功能(需要 `image_size` 参数)
1707
-
1708
- ### 视频生成模型
1709
-
1710
- #### 豆包 Seedance
1711
-
1712
- | 模型 | Provider | 说明 | 参数 |
1713
- |------|----------|------|------|
1714
- | `doubao-seedance-1-0-pro-fast-251015` | `doubao` | 快速版(推荐) | 时长: 1-10秒,宽高比: 16:9/9:16/1:1 |
1715
- | `doubao-seedance-1-0-pro-250528` | `doubao` | 专业版 | 时长: 1-10秒,宽高比: 16:9/9:16/1:1 |
1716
- | `doubao-seedance-1-0-lite-t2v-250428` | `doubao` | 轻量版(文生视频) | 时长: 1-10秒 |
1717
- | `doubao-seedance-1-0-lite-i2v-250428` | `doubao` | 轻量版(图生视频) | 时长: 1-10秒 |
1718
-
1719
- #### OpenAI Sora
1720
-
1721
- | 模型 | Provider | 说明 | 参数 |
1722
- |------|----------|------|------|
1723
- | `sora-2` | `api2img` | 标准模型(默认) | 时长: 4/8/12秒,分辨率: 720x1280, 1280x720, 1024x1792, 1792x1024 |
1724
- | `sora-2-pro` | `api2img` | 专业版模型 | 时长: 4/8/12秒,分辨率: 720x1280, 1280x720, 1024x1792, 1792x1024 |
1725
-
1726
- **特性说明:**
1727
- - **豆包 Seedance**: 支持文本生成视频和图像生成视频,URL 直接返回
1728
- - **OpenAI Sora**: 支持文本生成视频和图像生成视频(Base64/URL),需要流式下载
1729
- - **Provider 选择**:
1730
- - 豆包: 仅支持 `doubao` provider
1731
- - OpenAI: 支持 `api2img` provider
1732
-
1733
- ## 错误处理
1734
-
1735
- ```typescript
1736
- try {
1737
- const response = await model.invoke([
1738
- new HumanMessage('Hello!'),
1739
- ]);
1740
- console.log(response.content);
1741
- } catch (error) {
1742
- console.error('API 调用失败:', error);
1743
- if (error instanceof Error) {
1744
- console.error('错误消息:', error.message);
1745
- }
1746
- }
1747
- ```
1748
-
1749
- ## 开发
1750
-
1751
- ### 构建
1752
-
1753
- ```bash
1754
- npm run build
1755
- ```
1756
-
1757
- ### 测试
1758
-
1759
- ```bash
1760
- npm test # 运行所有单元测试
1761
- npm run test:llm # 运行 llm.ts 单元测试(mock,不需要后端)
1762
- npm run test:llm-real # 运行 llm.ts 真实集成测试(需要运行中的后端 + AUTH_TOKEN)
1763
-
1764
- # 其他特定测试
1765
- npm run test:stream
1766
- npm run test:image-generation
1767
- npm run test:video-generation
1768
- ```
1769
-
1770
- #### 真实集成测试
1771
-
1772
- `llm.real.test.ts` 通过运行中的后端代理测试 `createProvider` 和 `checkModel`:
1773
-
1774
- 1. 确保后端运行在 `http://localhost:8000`
1775
- 2. 在 `ai-world-sdk/.env` 中配置 `AUTH_TOKEN=your_jwt_token`
1776
- 3. 运行 `npm run test:llm-real`
1777
-
1778
- 测试覆盖 OpenAI (api2img)、Gemini、Anthropic 的非流式和流式文本生成。
1779
- 图像生成请手动运行 `example.test.ts` 中的相关用例。
1780
-
1781
- ## 参考链接
1782
-
1783
- - [Vercel AI SDK](https://ai-sdk.dev/docs) - `createProvider` 基于此构建,推荐使用 `generateText`、`streamText`、`generateImage` 等标准函数
1784
- - [LangChain.js](https://github.com/langchain-ai/langchainjs) - 设计灵感来源
1785
- - [火山引擎方舟平台](https://www.volcengine.com/docs/82379) - 图像/视频生成 API 文档
1786
-
1787
- ## 许可证
1788
-
1789
- MIT
1790
-
1791
- ## 更新日志
1792
-
1793
- ### 1.2.1
1794
- - ✨ 导出 `AIEndpointType` 类型,方便外部使用 `createProvider` 时引用端点类型
1795
-
1796
- ### 1.0.3
1797
- - ✨ 新增 Google Gemini 图像生成客户端
1798
- - ✨ 全局配置支持自动从浏览器环境获取
1799
- - ✨ 新增调试模式
1800
- - 🔧 改进日志输出
1801
-
1802
- ### 1.0.0
1803
- - ✨ 初始版本发布
1804
- - ✨ 支持聊天模型、图像生成、视频生成
1805
- - ✨ 兼容 LangChain.js 接口风格