ai-world-sdk 1.0.7 → 1.0.9
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 +76 -3
- package/dist/__tests__/example.test.js +109 -61
- package/dist/gemini-image-generation.d.ts +69 -0
- package/dist/gemini-image-generation.js +124 -1
- package/dist/index.d.ts +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -29,7 +29,7 @@ npm install ai-world-sdk
|
|
|
29
29
|
import { sdkConfig } from 'ai-world-sdk';
|
|
30
30
|
|
|
31
31
|
// 设置全局配置(只需一次)
|
|
32
|
-
sdkConfig.setBaseUrl('
|
|
32
|
+
sdkConfig.setBaseUrl('your-base-url');
|
|
33
33
|
sdkConfig.setToken('your-jwt-token');
|
|
34
34
|
sdkConfig.setDebug(true); // 可选:启用调试模式
|
|
35
35
|
|
|
@@ -233,6 +233,48 @@ const result2 = await client.generate({
|
|
|
233
233
|
temperature: 0.7, // 可选: 0.0-2.0
|
|
234
234
|
max_output_tokens: 1000, // 可选
|
|
235
235
|
});
|
|
236
|
+
|
|
237
|
+
// 使用 aihubmix provider(通过 aihubmix 代理服务)
|
|
238
|
+
const aihubmixClient = new GeminiImageGenerationClient({
|
|
239
|
+
provider: 'aihubmix', // 使用 aihubmix 代理
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
const result3 = await aihubmixClient.generate({
|
|
243
|
+
prompt: 'A beautiful landscape with mountains',
|
|
244
|
+
model: 'gemini-3-pro-image-preview',
|
|
245
|
+
aspect_ratio: '16:9',
|
|
246
|
+
image_size: '1K',
|
|
247
|
+
number_of_images: 1,
|
|
248
|
+
response_modalities: ['IMAGE'],
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
// 图像编辑(使用文本提示编辑图片)
|
|
252
|
+
const editResult = await client.edit({
|
|
253
|
+
prompt: 'Add a small wizard hat on the cat\'s head',
|
|
254
|
+
image: 'data:image/png;base64,iVBORw0KGgo...', // base64 编码的图片数据或 data URL
|
|
255
|
+
model: 'gemini-2.5-flash-image',
|
|
256
|
+
aspect_ratio: '1:1',
|
|
257
|
+
response_modalities: ['IMAGE'],
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
// 多轮图片修改(迭代式优化图片)
|
|
261
|
+
// 第一轮:创建初始图片
|
|
262
|
+
const firstResponse = await client.chat({
|
|
263
|
+
message: 'Create a vibrant infographic about photosynthesis',
|
|
264
|
+
model: 'gemini-3-pro-image-preview',
|
|
265
|
+
aspect_ratio: '16:9',
|
|
266
|
+
response_modalities: ['TEXT', 'IMAGE'],
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
// 后续轮次:修改图片(使用返回的 chat_id)
|
|
270
|
+
const secondResponse = await client.chat({
|
|
271
|
+
chat_id: firstResponse.chat_id,
|
|
272
|
+
message: 'Update this infographic to be in Spanish',
|
|
273
|
+
model: 'gemini-3-pro-image-preview',
|
|
274
|
+
aspect_ratio: '16:9',
|
|
275
|
+
image_size: '2K',
|
|
276
|
+
response_modalities: ['TEXT', 'IMAGE'],
|
|
277
|
+
});
|
|
236
278
|
```
|
|
237
279
|
|
|
238
280
|
**参数说明:**
|
|
@@ -250,6 +292,11 @@ const result2 = await client.generate({
|
|
|
250
292
|
|
|
251
293
|
**支持的宽高比:** `1:1`, `2:3`, `3:2`, `3:4`, `4:3`, `4:5`, `5:4`, `9:16`, `16:9`, `21:9`
|
|
252
294
|
|
|
295
|
+
**Provider 说明:**
|
|
296
|
+
|
|
297
|
+
- `provider: 'gemini'`(默认)- 直接使用 Google Gemini 官方 API
|
|
298
|
+
- `provider: 'aihubmix'` - 通过 aihubmix 代理服务调用,适合需要统一管理多个 API 的场景
|
|
299
|
+
|
|
253
300
|
**模型对比:**
|
|
254
301
|
|
|
255
302
|
| 模型 | 分辨率 | 特点 | 适用场景 |
|
|
@@ -257,6 +304,17 @@ const result2 = await client.generate({
|
|
|
257
304
|
| `gemini-2.5-flash-image` | 1024px | 快速、高效、成本低 | 日常使用、批量生成 |
|
|
258
305
|
| `gemini-3-pro-image-preview` | 1K/2K/4K | 专业级、高分辨率、高级功能 | 专业设计、高分辨率需求 |
|
|
259
306
|
|
|
307
|
+
**图像编辑和多轮修改:**
|
|
308
|
+
|
|
309
|
+
- **`edit()`** - 图像编辑:使用文本提示编辑图片,支持添加、移除或修改元素
|
|
310
|
+
- 需要提供输入图片(base64 编码或 data URL)
|
|
311
|
+
- 适用于单次编辑操作
|
|
312
|
+
|
|
313
|
+
- **`chat()`** - 多轮图片修改:通过对话迭代式优化图片
|
|
314
|
+
- 首次调用创建新的聊天会话,返回 `chat_id`
|
|
315
|
+
- 后续调用使用 `chat_id` 继续对话
|
|
316
|
+
- 推荐使用 `gemini-3-pro-image-preview` 模型进行多轮编辑
|
|
317
|
+
|
|
260
318
|
### 视频生成
|
|
261
319
|
|
|
262
320
|
#### VideoGenerationClient
|
|
@@ -290,7 +348,7 @@ const result = await client.poll(task.id, {
|
|
|
290
348
|
import { sdkConfig } from 'ai-world-sdk';
|
|
291
349
|
|
|
292
350
|
// 设置配置
|
|
293
|
-
sdkConfig.setBaseUrl('
|
|
351
|
+
sdkConfig.setBaseUrl('your-base-url');
|
|
294
352
|
sdkConfig.setToken('your-jwt-token');
|
|
295
353
|
sdkConfig.setHeaders({ 'X-Custom-Header': 'value' });
|
|
296
354
|
sdkConfig.setDebug(true);
|
|
@@ -345,11 +403,26 @@ const gptModel = new ChatOpenAI({
|
|
|
345
403
|
|
|
346
404
|
// Gemini 模型(通过 aihubmix)
|
|
347
405
|
const geminiModel = new ChatGoogleGenerativeAI({
|
|
348
|
-
modelName: 'gemini-2.5-flash
|
|
406
|
+
modelName: 'gemini-2.5-flash',
|
|
349
407
|
temperature: 0.7,
|
|
350
408
|
provider: 'aihubmix',
|
|
351
409
|
});
|
|
352
410
|
|
|
411
|
+
// Gemini 图像生成(通过 aihubmix)
|
|
412
|
+
import { GeminiImageGenerationClient } from 'ai-world-sdk';
|
|
413
|
+
|
|
414
|
+
const geminiImageClient = new GeminiImageGenerationClient({
|
|
415
|
+
provider: 'aihubmix',
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
const imageResult = await geminiImageClient.generate({
|
|
419
|
+
prompt: 'A beautiful landscape',
|
|
420
|
+
model: 'gemini-3-pro-image-preview',
|
|
421
|
+
aspect_ratio: '16:9',
|
|
422
|
+
image_size: '1K',
|
|
423
|
+
response_modalities: ['IMAGE'],
|
|
424
|
+
});
|
|
425
|
+
|
|
353
426
|
// Claude 模型(通过 aihubmix)
|
|
354
427
|
const claudeModel = new ChatAnthropic({
|
|
355
428
|
modelName: 'claude-3-sonnet-20240229',
|
|
@@ -228,38 +228,6 @@ describe("Langchain SDK Tests", () => {
|
|
|
228
228
|
console.log("响应内容:", content);
|
|
229
229
|
}
|
|
230
230
|
}, 60000);
|
|
231
|
-
test("ChatGoogleGenerativeAI - aihubmix.com 图像生成", async () => {
|
|
232
|
-
const gemini = new index_1.ChatGoogleGenerativeAI({
|
|
233
|
-
modelName: "gemini-3-pro-image-preview",
|
|
234
|
-
temperature: 0.7,
|
|
235
|
-
provider: "aihubmix",
|
|
236
|
-
});
|
|
237
|
-
const response = await gemini.invoke([
|
|
238
|
-
new index_1.HumanMessage("请生成一张展示人工智能概念的图片"),
|
|
239
|
-
]);
|
|
240
|
-
expect(response).toBeDefined();
|
|
241
|
-
expect(response.content).toBeDefined();
|
|
242
|
-
// 图像生成响应可能包含文本和图像数据
|
|
243
|
-
// 检查响应内容(可能是字符串、数组或包含图像的对象)
|
|
244
|
-
const content = response.content;
|
|
245
|
-
if (typeof content === "string") {
|
|
246
|
-
console.log("✅ aihubmix.com 图像生成测试成功(文本响应)");
|
|
247
|
-
console.log("AI:", content);
|
|
248
|
-
}
|
|
249
|
-
else if (Array.isArray(content)) {
|
|
250
|
-
// 多模态响应,可能包含图像
|
|
251
|
-
const hasImage = content.some((item) => item?.type === "image_url" ||
|
|
252
|
-
item?.image_url ||
|
|
253
|
-
(typeof item === "string" && item.startsWith("data:image")));
|
|
254
|
-
console.log("✅ aihubmix.com 图像生成测试成功(多模态响应)");
|
|
255
|
-
console.log("响应类型: 数组,包含图像:", hasImage);
|
|
256
|
-
console.log("响应内容:", JSON.stringify(content, null, 2));
|
|
257
|
-
}
|
|
258
|
-
else {
|
|
259
|
-
console.log("✅ aihubmix.com 图像生成测试成功(其他格式)");
|
|
260
|
-
console.log("响应内容:", content);
|
|
261
|
-
}
|
|
262
|
-
}, 60000);
|
|
263
231
|
test("DoubaoImageGenerationClient - 基础图像生成", async () => {
|
|
264
232
|
const imageClient = new index_1.DoubaoImageGenerationClient({});
|
|
265
233
|
const result = await imageClient.generate({
|
|
@@ -592,7 +560,7 @@ describe("Langchain SDK Tests", () => {
|
|
|
592
560
|
prompt: 'A beautiful sunset over the ocean',
|
|
593
561
|
model: 'gemini-3-pro-image-preview',
|
|
594
562
|
aspect_ratio: '16:9',
|
|
595
|
-
image_size: '
|
|
563
|
+
image_size: '1K', // 仅适用于 gemini-3-pro-image-preview
|
|
596
564
|
number_of_images: 1,
|
|
597
565
|
response_modalities: ['IMAGE'], // 仅返回图片
|
|
598
566
|
});
|
|
@@ -613,41 +581,121 @@ describe("Langchain SDK Tests", () => {
|
|
|
613
581
|
console.log("图像描述:", result.text);
|
|
614
582
|
}
|
|
615
583
|
}, 120000);
|
|
616
|
-
test("GeminiImageGenerationClient -
|
|
617
|
-
const imageClient = new index_1.GeminiImageGenerationClient({
|
|
584
|
+
test("GeminiImageGenerationClient - 使用 aihubmix provider", async () => {
|
|
585
|
+
const imageClient = new index_1.GeminiImageGenerationClient({
|
|
586
|
+
provider: "aihubmix",
|
|
587
|
+
});
|
|
618
588
|
const result = await imageClient.generate({
|
|
619
|
-
prompt:
|
|
620
|
-
model:
|
|
621
|
-
|
|
622
|
-
|
|
589
|
+
prompt: 'A beautiful sunset over the ocean',
|
|
590
|
+
model: 'gemini-3-pro-image-preview',
|
|
591
|
+
aspect_ratio: '16:9',
|
|
592
|
+
image_size: '1K',
|
|
593
|
+
number_of_images: 1,
|
|
594
|
+
response_modalities: ['IMAGE'], // 仅返回图片
|
|
623
595
|
});
|
|
624
596
|
expect(result).toBeDefined();
|
|
597
|
+
expect(result.created).toBeDefined();
|
|
598
|
+
expect(typeof result.created).toBe("number");
|
|
625
599
|
expect(result.data).toBeDefined();
|
|
626
600
|
expect(Array.isArray(result.data)).toBe(true);
|
|
627
|
-
expect(result.data.length).
|
|
628
|
-
|
|
601
|
+
expect(result.data.length).toBeGreaterThan(0);
|
|
602
|
+
result.data.forEach((item) => {
|
|
603
|
+
expect(item).toBeDefined();
|
|
604
|
+
expect(item.url || item.b64_json).toBeDefined();
|
|
605
|
+
});
|
|
606
|
+
console.log("✅ GeminiImageGenerationClient (aihubmix provider) 测试成功");
|
|
629
607
|
console.log(`生成图像数量: ${result.data.length}`);
|
|
608
|
+
console.log("图像 URL:", result.data[0]?.url || ("Base64 编码" + result.data[0]?.b64_json));
|
|
609
|
+
if (result.text) {
|
|
610
|
+
console.log("图像描述:", result.text);
|
|
611
|
+
}
|
|
630
612
|
}, 120000);
|
|
631
|
-
test("GeminiImageGenerationClient -
|
|
613
|
+
test("GeminiImageGenerationClient - 图像编辑", async () => {
|
|
632
614
|
const imageClient = new index_1.GeminiImageGenerationClient({});
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
615
|
+
// 首先生成一张基础图片
|
|
616
|
+
const generateResult = await imageClient.generate({
|
|
617
|
+
prompt: 'A simple red apple on a white background',
|
|
618
|
+
model: 'gemini-2.5-flash-image',
|
|
619
|
+
aspect_ratio: '1:1',
|
|
620
|
+
response_modalities: ['IMAGE'],
|
|
621
|
+
});
|
|
622
|
+
expect(generateResult).toBeDefined();
|
|
623
|
+
expect(generateResult.data).toBeDefined();
|
|
624
|
+
expect(generateResult.data.length).toBeGreaterThan(0);
|
|
625
|
+
// 获取第一张图片的 base64 数据
|
|
626
|
+
const firstImage = generateResult.data[0];
|
|
627
|
+
expect(firstImage).toBeDefined();
|
|
628
|
+
// 提取 base64 数据(优先使用 b64_json,否则从 text 中提取)
|
|
629
|
+
let base64Image;
|
|
630
|
+
if (firstImage.b64_json) {
|
|
631
|
+
base64Image = firstImage.b64_json;
|
|
649
632
|
}
|
|
633
|
+
else if (firstImage.text && firstImage.text.startsWith('data:')) {
|
|
634
|
+
// 从 data URL 中提取 base64 部分
|
|
635
|
+
base64Image = firstImage.text.split(',')[1];
|
|
636
|
+
}
|
|
637
|
+
else {
|
|
638
|
+
throw new Error('无法获取图片的 base64 数据');
|
|
639
|
+
}
|
|
640
|
+
expect(base64Image).toBeDefined();
|
|
641
|
+
// 使用编辑功能添加元素
|
|
642
|
+
const editResult = await imageClient.edit({
|
|
643
|
+
prompt: 'Add a small green leaf on top of the apple',
|
|
644
|
+
image: base64Image, // 直接使用 base64 字符串
|
|
645
|
+
model: 'gemini-2.5-flash-image',
|
|
646
|
+
aspect_ratio: '1:1',
|
|
647
|
+
response_modalities: ['IMAGE'],
|
|
648
|
+
});
|
|
649
|
+
expect(editResult).toBeDefined();
|
|
650
|
+
expect(editResult.created).toBeDefined();
|
|
651
|
+
expect(editResult.data).toBeDefined();
|
|
652
|
+
expect(Array.isArray(editResult.data)).toBe(true);
|
|
653
|
+
expect(editResult.data.length).toBeGreaterThan(0);
|
|
654
|
+
editResult.data.forEach((item) => {
|
|
655
|
+
expect(item).toBeDefined();
|
|
656
|
+
expect(item.url || item.b64_json).toBeDefined();
|
|
657
|
+
});
|
|
658
|
+
console.log("✅ GeminiImageGenerationClient 图像编辑测试成功");
|
|
659
|
+
console.log(`编辑后图像数量: ${editResult.data.length}`);
|
|
650
660
|
}, 180000);
|
|
661
|
+
test("GeminiImageGenerationClient - 多轮图片修改", async () => {
|
|
662
|
+
const imageClient = new index_1.GeminiImageGenerationClient({});
|
|
663
|
+
// 第一轮:创建初始图片
|
|
664
|
+
const firstResponse = await imageClient.chat({
|
|
665
|
+
message: 'Create a vibrant infographic that explains photosynthesis as if it were a recipe for a plant\'s favorite food. Show the "ingredients" (sunlight, water, CO2) and the "finished dish" (sugar/energy). The style should be like a page from a colorful kids\' cookbook, suitable for a 4th grader.',
|
|
666
|
+
model: 'gemini-3-pro-image-preview',
|
|
667
|
+
aspect_ratio: '16:9',
|
|
668
|
+
response_modalities: ['TEXT', 'IMAGE'],
|
|
669
|
+
});
|
|
670
|
+
expect(firstResponse).toBeDefined();
|
|
671
|
+
expect(firstResponse.chat_id).toBeDefined();
|
|
672
|
+
expect(typeof firstResponse.chat_id).toBe("string");
|
|
673
|
+
expect(firstResponse.data).toBeDefined();
|
|
674
|
+
expect(Array.isArray(firstResponse.data)).toBe(true);
|
|
675
|
+
expect(firstResponse.data.length).toBeGreaterThan(0);
|
|
676
|
+
console.log("✅ 第一轮图片生成成功");
|
|
677
|
+
console.log(`Chat ID: ${firstResponse.chat_id}`);
|
|
678
|
+
console.log(`生成图像数量: ${firstResponse.data.length}`);
|
|
679
|
+
// 第二轮:修改图片(将语言改为西班牙语)
|
|
680
|
+
const secondResponse = await imageClient.chat({
|
|
681
|
+
chat_id: firstResponse.chat_id,
|
|
682
|
+
message: 'Update this infographic to be in Spanish. Do not change any other elements of the image.',
|
|
683
|
+
model: 'gemini-3-pro-image-preview',
|
|
684
|
+
aspect_ratio: '16:9',
|
|
685
|
+
image_size: '2K',
|
|
686
|
+
response_modalities: ['TEXT', 'IMAGE'],
|
|
687
|
+
});
|
|
688
|
+
expect(secondResponse).toBeDefined();
|
|
689
|
+
expect(secondResponse.chat_id).toBe(firstResponse.chat_id); // chat_id 应该保持一致
|
|
690
|
+
expect(secondResponse.data).toBeDefined();
|
|
691
|
+
expect(Array.isArray(secondResponse.data)).toBe(true);
|
|
692
|
+
expect(secondResponse.data.length).toBeGreaterThan(0);
|
|
693
|
+
console.log("✅ 第二轮图片修改成功");
|
|
694
|
+
console.log(`修改后图像数量: ${secondResponse.data.length}`);
|
|
695
|
+
if (secondResponse.text) {
|
|
696
|
+
console.log("文本响应:", secondResponse.text);
|
|
697
|
+
}
|
|
698
|
+
}, 240000);
|
|
651
699
|
test("DoubaoImageGenerationClient - quality 参数测试", async () => {
|
|
652
700
|
const imageClient = new index_1.DoubaoImageGenerationClient({});
|
|
653
701
|
const qualities = ["standard", "hd"];
|
|
@@ -662,7 +710,7 @@ describe("Langchain SDK Tests", () => {
|
|
|
662
710
|
expect(result).toBeDefined();
|
|
663
711
|
expect(result.data).toBeDefined();
|
|
664
712
|
expect(result.data.length).toBeGreaterThan(0);
|
|
665
|
-
console.log(`✅ quality ${quality}
|
|
713
|
+
console.log(`✅ quality ${quality} 测试成功`, result.data);
|
|
666
714
|
}
|
|
667
715
|
}, 180000);
|
|
668
716
|
test("DoubaoImageGenerationClient - style 参数测试", async () => {
|
|
@@ -679,7 +727,7 @@ describe("Langchain SDK Tests", () => {
|
|
|
679
727
|
expect(result).toBeDefined();
|
|
680
728
|
expect(result.data).toBeDefined();
|
|
681
729
|
expect(result.data.length).toBeGreaterThan(0);
|
|
682
|
-
console.log(`✅ style ${style}
|
|
730
|
+
console.log(`✅ style ${style} 测试成功`, result.data);
|
|
683
731
|
}
|
|
684
732
|
}, 180000);
|
|
685
733
|
test("DoubaoImageGenerationClient - response_format 参数测试", async () => {
|
|
@@ -719,7 +767,7 @@ describe("Langchain SDK Tests", () => {
|
|
|
719
767
|
expect(result).toBeDefined();
|
|
720
768
|
expect(result.data).toBeDefined();
|
|
721
769
|
expect(result.data.length).toBeGreaterThan(0);
|
|
722
|
-
console.log("✅ watermark 参数测试成功");
|
|
770
|
+
console.log("✅ watermark 参数测试成功", result.data);
|
|
723
771
|
}, 120000);
|
|
724
772
|
test("sdkConfig - 全局配置测试", () => {
|
|
725
773
|
const originalBaseUrl = index_1.sdkConfig.getServerUrl();
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* Google Gemini 图像生成客户端
|
|
4
4
|
*/
|
|
5
5
|
export interface GeminiImageGenerationConfig {
|
|
6
|
+
provider?: "aihubmix" | "gemini";
|
|
6
7
|
baseUrl?: string;
|
|
7
8
|
headers?: Record<string, string>;
|
|
8
9
|
}
|
|
@@ -27,8 +28,35 @@ export interface GeminiImageGenerationResponse {
|
|
|
27
28
|
data: GeminiImageData[];
|
|
28
29
|
text?: string;
|
|
29
30
|
}
|
|
31
|
+
export interface GeminiImageEditRequest {
|
|
32
|
+
prompt: string;
|
|
33
|
+
image: string;
|
|
34
|
+
model?: string;
|
|
35
|
+
provider?: "aihubmix" | "gemini";
|
|
36
|
+
aspect_ratio?: "1:1" | "2:3" | "3:2" | "3:4" | "4:3" | "4:5" | "5:4" | "9:16" | "16:9" | "21:9";
|
|
37
|
+
image_size?: "1K" | "2K" | "4K";
|
|
38
|
+
response_modalities?: ("TEXT" | "IMAGE")[];
|
|
39
|
+
user?: string;
|
|
40
|
+
}
|
|
41
|
+
export interface GeminiImageChatRequest {
|
|
42
|
+
message: string;
|
|
43
|
+
chat_id?: string;
|
|
44
|
+
model?: string;
|
|
45
|
+
provider?: "aihubmix" | "gemini";
|
|
46
|
+
aspect_ratio?: "1:1" | "2:3" | "3:2" | "3:4" | "4:3" | "4:5" | "5:4" | "9:16" | "16:9" | "21:9";
|
|
47
|
+
image_size?: "1K" | "2K" | "4K";
|
|
48
|
+
response_modalities?: ("TEXT" | "IMAGE")[];
|
|
49
|
+
user?: string;
|
|
50
|
+
}
|
|
51
|
+
export interface GeminiImageChatResponse {
|
|
52
|
+
chat_id: string;
|
|
53
|
+
created: number;
|
|
54
|
+
data: GeminiImageData[];
|
|
55
|
+
text?: string;
|
|
56
|
+
}
|
|
30
57
|
export declare class GeminiImageGenerationClient {
|
|
31
58
|
private headers;
|
|
59
|
+
private provider;
|
|
32
60
|
constructor(config?: GeminiImageGenerationConfig);
|
|
33
61
|
/**
|
|
34
62
|
* Generate images
|
|
@@ -41,4 +69,45 @@ export declare class GeminiImageGenerationClient {
|
|
|
41
69
|
* - number_of_images: 生成图片数量(1-4)
|
|
42
70
|
*/
|
|
43
71
|
generate(request: GeminiImageGenerationRequest): Promise<GeminiImageGenerationResponse>;
|
|
72
|
+
/**
|
|
73
|
+
* Edit images
|
|
74
|
+
* 编辑图像
|
|
75
|
+
*
|
|
76
|
+
* 使用文本提示编辑图片,支持添加、移除或修改元素
|
|
77
|
+
*
|
|
78
|
+
* 支持的参数:
|
|
79
|
+
* - image: base64 编码的图片数据,或 data URL(如 data:image/png;base64,...)
|
|
80
|
+
* - aspect_ratio: 宽高比
|
|
81
|
+
* - image_size: 图片大小(仅 gemini-3-pro-image-preview)
|
|
82
|
+
* - response_modalities: 响应模态
|
|
83
|
+
*/
|
|
84
|
+
edit(request: GeminiImageEditRequest): Promise<GeminiImageGenerationResponse>;
|
|
85
|
+
/**
|
|
86
|
+
* Chat with images (multi-turn image editing)
|
|
87
|
+
* 图像多轮对话(用于多轮图片修改)
|
|
88
|
+
*
|
|
89
|
+
* 支持通过多轮对话迭代式优化图片
|
|
90
|
+
*
|
|
91
|
+
* 使用示例:
|
|
92
|
+
* ```typescript
|
|
93
|
+
* // 第一轮:创建初始图片
|
|
94
|
+
* const firstResponse = await client.chat({
|
|
95
|
+
* message: "Create a vibrant infographic about photosynthesis"
|
|
96
|
+
* });
|
|
97
|
+
*
|
|
98
|
+
* // 后续轮次:修改图片(使用返回的 chat_id)
|
|
99
|
+
* const secondResponse = await client.chat({
|
|
100
|
+
* chat_id: firstResponse.chat_id,
|
|
101
|
+
* message: "Update this infographic to be in Spanish"
|
|
102
|
+
* });
|
|
103
|
+
* ```
|
|
104
|
+
*
|
|
105
|
+
* 支持的参数:
|
|
106
|
+
* - message: 当前轮次的提示词
|
|
107
|
+
* - chat_id: 聊天 ID(用于多轮对话,首次请求时不需要)
|
|
108
|
+
* - aspect_ratio: 宽高比
|
|
109
|
+
* - image_size: 图片大小(仅 gemini-3-pro-image-preview)
|
|
110
|
+
* - response_modalities: 响应模态
|
|
111
|
+
*/
|
|
112
|
+
chat(request: GeminiImageChatRequest): Promise<GeminiImageChatResponse>;
|
|
44
113
|
}
|
|
@@ -9,15 +9,21 @@ const config_1 = require("./config");
|
|
|
9
9
|
const log_1 = require("./log");
|
|
10
10
|
class GeminiImageGenerationClient {
|
|
11
11
|
constructor(config) {
|
|
12
|
+
// 确定 provider(默认为 gemini)
|
|
13
|
+
this.provider = config?.provider || "gemini";
|
|
12
14
|
// 合并全局 headers 和配置 headers
|
|
13
15
|
const globalHeaders = config_1.sdkConfig.getHeaders();
|
|
14
16
|
this.headers = {
|
|
15
17
|
"Content-Type": "application/json",
|
|
16
18
|
"Authorization": `Bearer ${config_1.sdkConfig.getToken()}`,
|
|
17
|
-
"X-
|
|
19
|
+
"X-Provider": this.provider, // 在 header 中传递 provider,由后端确定 baseUrl
|
|
18
20
|
...globalHeaders,
|
|
19
21
|
...config?.headers,
|
|
20
22
|
};
|
|
23
|
+
// 如果明确指定了 baseUrl,也添加到 header 中
|
|
24
|
+
if (config?.baseUrl) {
|
|
25
|
+
this.headers["X-Base-Url"] = config.baseUrl;
|
|
26
|
+
}
|
|
21
27
|
}
|
|
22
28
|
/**
|
|
23
29
|
* Generate images
|
|
@@ -70,5 +76,122 @@ class GeminiImageGenerationClient {
|
|
|
70
76
|
(0, log_1.logResponse)(response.status, response.statusText, response.headers, data);
|
|
71
77
|
return data;
|
|
72
78
|
}
|
|
79
|
+
/**
|
|
80
|
+
* Edit images
|
|
81
|
+
* 编辑图像
|
|
82
|
+
*
|
|
83
|
+
* 使用文本提示编辑图片,支持添加、移除或修改元素
|
|
84
|
+
*
|
|
85
|
+
* 支持的参数:
|
|
86
|
+
* - image: base64 编码的图片数据,或 data URL(如 data:image/png;base64,...)
|
|
87
|
+
* - aspect_ratio: 宽高比
|
|
88
|
+
* - image_size: 图片大小(仅 gemini-3-pro-image-preview)
|
|
89
|
+
* - response_modalities: 响应模态
|
|
90
|
+
*/
|
|
91
|
+
async edit(request) {
|
|
92
|
+
const requestBody = {
|
|
93
|
+
prompt: request.prompt,
|
|
94
|
+
image: request.image,
|
|
95
|
+
model: request.model || "gemini-2.5-flash-image",
|
|
96
|
+
};
|
|
97
|
+
// 添加可选参数
|
|
98
|
+
if (request.aspect_ratio) {
|
|
99
|
+
requestBody.aspect_ratio = request.aspect_ratio;
|
|
100
|
+
}
|
|
101
|
+
if (request.image_size) {
|
|
102
|
+
requestBody.image_size = request.image_size;
|
|
103
|
+
}
|
|
104
|
+
if (request.response_modalities) {
|
|
105
|
+
requestBody.response_modalities = request.response_modalities;
|
|
106
|
+
}
|
|
107
|
+
if (request.user) {
|
|
108
|
+
requestBody.user = request.user;
|
|
109
|
+
}
|
|
110
|
+
if (request.provider) {
|
|
111
|
+
requestBody.provider = request.provider;
|
|
112
|
+
}
|
|
113
|
+
const url = `${config_1.sdkConfig.getServerUrl()}/api/gemini-image-proxy/edit`;
|
|
114
|
+
(0, log_1.logRequest)("POST", url, this.headers, { ...requestBody, image: "[base64 data]" });
|
|
115
|
+
const response = await fetch(url, {
|
|
116
|
+
method: "POST",
|
|
117
|
+
headers: this.headers,
|
|
118
|
+
body: JSON.stringify(requestBody),
|
|
119
|
+
});
|
|
120
|
+
if (!response.ok) {
|
|
121
|
+
const errorText = await response.text();
|
|
122
|
+
(0, log_1.logResponse)(response.status, response.statusText, response.headers, errorText);
|
|
123
|
+
throw new Error(`Gemini image edit API error: ${response.status} ${errorText}`);
|
|
124
|
+
}
|
|
125
|
+
const data = (await response.json());
|
|
126
|
+
(0, log_1.logResponse)(response.status, response.statusText, response.headers, data);
|
|
127
|
+
return data;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Chat with images (multi-turn image editing)
|
|
131
|
+
* 图像多轮对话(用于多轮图片修改)
|
|
132
|
+
*
|
|
133
|
+
* 支持通过多轮对话迭代式优化图片
|
|
134
|
+
*
|
|
135
|
+
* 使用示例:
|
|
136
|
+
* ```typescript
|
|
137
|
+
* // 第一轮:创建初始图片
|
|
138
|
+
* const firstResponse = await client.chat({
|
|
139
|
+
* message: "Create a vibrant infographic about photosynthesis"
|
|
140
|
+
* });
|
|
141
|
+
*
|
|
142
|
+
* // 后续轮次:修改图片(使用返回的 chat_id)
|
|
143
|
+
* const secondResponse = await client.chat({
|
|
144
|
+
* chat_id: firstResponse.chat_id,
|
|
145
|
+
* message: "Update this infographic to be in Spanish"
|
|
146
|
+
* });
|
|
147
|
+
* ```
|
|
148
|
+
*
|
|
149
|
+
* 支持的参数:
|
|
150
|
+
* - message: 当前轮次的提示词
|
|
151
|
+
* - chat_id: 聊天 ID(用于多轮对话,首次请求时不需要)
|
|
152
|
+
* - aspect_ratio: 宽高比
|
|
153
|
+
* - image_size: 图片大小(仅 gemini-3-pro-image-preview)
|
|
154
|
+
* - response_modalities: 响应模态
|
|
155
|
+
*/
|
|
156
|
+
async chat(request) {
|
|
157
|
+
const requestBody = {
|
|
158
|
+
message: request.message,
|
|
159
|
+
model: request.model || "gemini-3-pro-image-preview",
|
|
160
|
+
};
|
|
161
|
+
// 添加可选参数
|
|
162
|
+
if (request.chat_id) {
|
|
163
|
+
requestBody.chat_id = request.chat_id;
|
|
164
|
+
}
|
|
165
|
+
if (request.aspect_ratio) {
|
|
166
|
+
requestBody.aspect_ratio = request.aspect_ratio;
|
|
167
|
+
}
|
|
168
|
+
if (request.image_size) {
|
|
169
|
+
requestBody.image_size = request.image_size;
|
|
170
|
+
}
|
|
171
|
+
if (request.response_modalities) {
|
|
172
|
+
requestBody.response_modalities = request.response_modalities;
|
|
173
|
+
}
|
|
174
|
+
if (request.user) {
|
|
175
|
+
requestBody.user = request.user;
|
|
176
|
+
}
|
|
177
|
+
if (request.provider) {
|
|
178
|
+
requestBody.provider = request.provider;
|
|
179
|
+
}
|
|
180
|
+
const url = `${config_1.sdkConfig.getServerUrl()}/api/gemini-image-proxy/chat`;
|
|
181
|
+
(0, log_1.logRequest)("POST", url, this.headers, requestBody);
|
|
182
|
+
const response = await fetch(url, {
|
|
183
|
+
method: "POST",
|
|
184
|
+
headers: this.headers,
|
|
185
|
+
body: JSON.stringify(requestBody),
|
|
186
|
+
});
|
|
187
|
+
if (!response.ok) {
|
|
188
|
+
const errorText = await response.text();
|
|
189
|
+
(0, log_1.logResponse)(response.status, response.statusText, response.headers, errorText);
|
|
190
|
+
throw new Error(`Gemini image chat API error: ${response.status} ${errorText}`);
|
|
191
|
+
}
|
|
192
|
+
const data = (await response.json());
|
|
193
|
+
(0, log_1.logResponse)(response.status, response.statusText, response.headers, data);
|
|
194
|
+
return data;
|
|
195
|
+
}
|
|
73
196
|
}
|
|
74
197
|
exports.GeminiImageGenerationClient = GeminiImageGenerationClient;
|
package/dist/index.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ import { GeminiImageGenerationClient, type GeminiImageGenerationConfig, type Gem
|
|
|
10
10
|
import { VideoGenerationClient, type VideoGenerationConfig, type VideoGenerationRequest, type ContentGenerationTaskID, type ContentGenerationTask } from "./video_generation";
|
|
11
11
|
import { sdkConfig } from "./config";
|
|
12
12
|
export { BaseMessage, HumanMessage, AIMessage, SystemMessage, AIMessageChunk, type MessageContent, type AIMessageChunkData, } from "./messages";
|
|
13
|
-
export { BaseChatModel, type BaseChatModelParams, type ToolDefinition, type BindOptions, } from "./base";
|
|
13
|
+
export { BaseChatModel, type BaseChatModelParams, type AIModelProvider, type ToolDefinition, type BindOptions, } from "./base";
|
|
14
14
|
export { ChatOpenAI } from "./chat_models/openai";
|
|
15
15
|
export { ChatGoogleGenerativeAI } from "./chat_models/google";
|
|
16
16
|
export { ChatAnthropic } from "./chat_models/anthropic";
|
package/package.json
CHANGED