@maiyunnet/kebab 8.0.6 → 8.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/doc/kebab-rag.md CHANGED
@@ -1385,7 +1385,7 @@ index/variables/VER.md
1385
1385
 
1386
1386
  # Variable: VER
1387
1387
 
1388
- > `const` **VER**: `"8.0.6"` = `'8.0.6'`
1388
+ > `const` **VER**: `"8.1.0"` = `'8.1.0'`
1389
1389
 
1390
1390
  Defined in: [index.ts:10](https://github.com/maiyunnet/kebab/blob/master/index.ts#L10)
1391
1391
 
@@ -1432,7 +1432,7 @@ lib/ai/classes/Ai.md
1432
1432
 
1433
1433
  # Class: Ai
1434
1434
 
1435
- Defined in: [lib/ai.ts:49](https://github.com/maiyunnet/kebab/blob/master/lib/ai.ts#L49)
1435
+ Defined in: [lib/ai.ts:58](https://github.com/maiyunnet/kebab/blob/master/lib/ai.ts#L58)
1436
1436
 
1437
1437
  ## Constructors
1438
1438
 
@@ -1440,7 +1440,7 @@ Defined in: [lib/ai.ts:49](https://github.com/maiyunnet/kebab/blob/master/lib/ai
1440
1440
 
1441
1441
  > **new Ai**(`ctrEtc`, `opt`): `Ai`
1442
1442
 
1443
- Defined in: [lib/ai.ts:56](https://github.com/maiyunnet/kebab/blob/master/lib/ai.ts#L56)
1443
+ Defined in: [lib/ai.ts:71](https://github.com/maiyunnet/kebab/blob/master/lib/ai.ts#L71)
1444
1444
 
1445
1445
  #### Parameters
1446
1446
 
@@ -1462,9 +1462,25 @@ Defined in: [lib/ai.ts:56](https://github.com/maiyunnet/kebab/blob/master/lib/ai
1462
1462
 
1463
1463
  > `readonly` **link**: `OpenAI`
1464
1464
 
1465
- Defined in: [lib/ai.ts:52](https://github.com/maiyunnet/kebab/blob/master/lib/ai.ts#L52)
1465
+ Defined in: [lib/ai.ts:61](https://github.com/maiyunnet/kebab/blob/master/lib/ai.ts#L61)
1466
+
1467
+ openai 原生对象
1468
+
1469
+ ## Accessors
1470
+
1471
+ ### service
1472
+
1473
+ #### Get Signature
1474
+
1475
+ > **get** **service**(): [`ESERVICE`](../enumerations/ESERVICE.md)
1476
+
1477
+ Defined in: [lib/ai.ts:143](https://github.com/maiyunnet/kebab/blob/master/lib/ai.ts#L143)
1466
1478
 
1467
- openai 原生对象,建议只读
1479
+ 获取当前服务商
1480
+
1481
+ ##### Returns
1482
+
1483
+ [`ESERVICE`](../enumerations/ESERVICE.md)
1468
1484
 
1469
1485
  ## Methods
1470
1486
 
@@ -1476,7 +1492,7 @@ openai 原生对象,建议只读
1476
1492
 
1477
1493
  > **chat**(`body`): `Promise`\<`false` \| `APIPromise`\<`ChatCompletion`\>\>
1478
1494
 
1479
- Defined in: [lib/ai.ts:111](https://github.com/maiyunnet/kebab/blob/master/lib/ai.ts#L111)
1495
+ Defined in: [lib/ai.ts:148](https://github.com/maiyunnet/kebab/blob/master/lib/ai.ts#L148)
1480
1496
 
1481
1497
  创建非流式对话
1482
1498
 
@@ -1494,7 +1510,7 @@ Defined in: [lib/ai.ts:111](https://github.com/maiyunnet/kebab/blob/master/lib/a
1494
1510
 
1495
1511
  > **chat**(`body`): `Promise`\<`false` \| `APIPromise`\<`Stream`\<`ChatCompletionChunk`\>\>\>
1496
1512
 
1497
- Defined in: [lib/ai.ts:115](https://github.com/maiyunnet/kebab/blob/master/lib/ai.ts#L115)
1513
+ Defined in: [lib/ai.ts:152](https://github.com/maiyunnet/kebab/blob/master/lib/ai.ts#L152)
1498
1514
 
1499
1515
  创建流式对话
1500
1516
 
@@ -1514,7 +1530,7 @@ Defined in: [lib/ai.ts:115](https://github.com/maiyunnet/kebab/blob/master/lib/a
1514
1530
 
1515
1531
  > **embedding**(`body`): `Promise`\<`false` \| `APIPromise`\<`CreateEmbeddingResponse`\>\>
1516
1532
 
1517
- Defined in: [lib/ai.ts:135](https://github.com/maiyunnet/kebab/blob/master/lib/ai.ts#L135)
1533
+ Defined in: [lib/ai.ts:172](https://github.com/maiyunnet/kebab/blob/master/lib/ai.ts#L172)
1518
1534
 
1519
1535
  创建向量
1520
1536
 
@@ -1528,6 +1544,180 @@ Defined in: [lib/ai.ts:135](https://github.com/maiyunnet/kebab/blob/master/lib/a
1528
1544
 
1529
1545
  `Promise`\<`false` \| `APIPromise`\<`CreateEmbeddingResponse`\>\>
1530
1546
 
1547
+ ***
1548
+
1549
+ ### image()
1550
+
1551
+ > **image**(`opt`): `Promise`\<`false` \| \{ `list`: `object`[]; `request`: `string`; `seed`: `number`; \}\>
1552
+
1553
+ Defined in: [lib/ai.ts:186](https://github.com/maiyunnet/kebab/blob/master/lib/ai.ts#L186)
1554
+
1555
+ 生成图像,不支持 GEMINI、GROK 服务商
1556
+
1557
+ #### Parameters
1558
+
1559
+ ##### opt
1560
+
1561
+ ###### extend?
1562
+
1563
+ `boolean`
1564
+
1565
+ 模型是否自动优化提示词,默认为 false,但有些服务商可能无效
1566
+
1567
+ ###### imgs?
1568
+
1569
+ `string`[]
1570
+
1571
+ 参考图,请注意模型是否支持,以及是否支持多张,仅支持 ALICN、ALIAS、VOLCN、VOLAS 服务商
1572
+
1573
+ ###### model
1574
+
1575
+ `string`
1576
+
1577
+ ###### n?
1578
+
1579
+ `number`
1580
+
1581
+ ###### negative?
1582
+
1583
+ `string`
1584
+
1585
+ 负面提示词,用于引导模型避免生成某些内容
1586
+
1587
+ ###### prompt
1588
+
1589
+ `string`
1590
+
1591
+ 提示词
1592
+
1593
+ ###### seed?
1594
+
1595
+ `number`
1596
+
1597
+ 随机种子,默认为随机
1598
+
1599
+ ###### size
1600
+
1601
+ `number`[]
1602
+
1603
+ 长 x 宽,不同模型要求不同,如 [1664, 928]
1604
+
1605
+ #### Returns
1606
+
1607
+ `Promise`\<`false` \| \{ `list`: `object`[]; `request`: `string`; `seed`: `number`; \}\>
1608
+
1609
+ ***
1610
+
1611
+ ### poll()
1612
+
1613
+ > **poll**(`opt`): `Promise`\<`false` \| \{ `add?`: `number`; `end?`: `number`; `error?`: `string`; `start?`: `number`; `status`: `"PENDING"` \| `"RUNNING"` \| `"SUCCEEDED"` \| `"FAILED"` \| `"CANCELED"` \| `"UNKNOWN"`; `task`: `string`; `url?`: `string`; \}\>
1614
+
1615
+ Defined in: [lib/ai.ts:534](https://github.com/maiyunnet/kebab/blob/master/lib/ai.ts#L534)
1616
+
1617
+ 轮询任务
1618
+
1619
+ #### Parameters
1620
+
1621
+ ##### opt
1622
+
1623
+ ###### task
1624
+
1625
+ `string`
1626
+
1627
+ ###### type
1628
+
1629
+ `"video"`
1630
+
1631
+ #### Returns
1632
+
1633
+ `Promise`\<`false` \| \{ `add?`: `number`; `end?`: `number`; `error?`: `string`; `start?`: `number`; `status`: `"PENDING"` \| `"RUNNING"` \| `"SUCCEEDED"` \| `"FAILED"` \| `"CANCELED"` \| `"UNKNOWN"`; `task`: `string`; `url?`: `string`; \}\>
1634
+
1635
+ ***
1636
+
1637
+ ### video()
1638
+
1639
+ > **video**(`opt`): `Promise`\<`false` \| \{ `request`: `string`; `seed`: `number`; `status`: `"PENDING"` \| `"RUNNING"` \| `"SUCCEEDED"` \| `"FAILED"` \| `"CANCELED"` \| `"UNKNOWN"`; `task`: `string`; \}\>
1640
+
1641
+ Defined in: [lib/ai.ts:366](https://github.com/maiyunnet/kebab/blob/master/lib/ai.ts#L366)
1642
+
1643
+ 异步生成视频,仅支持 ALICN、ALIAS
1644
+
1645
+ #### Parameters
1646
+
1647
+ ##### opt
1648
+
1649
+ ###### audio?
1650
+
1651
+ `string` \| `boolean`
1652
+
1653
+ 视频声音,默认 false,true 代表自动配音,字符串代表自定义音频网址
1654
+
1655
+ ###### duration?
1656
+
1657
+ `number`
1658
+
1659
+ 视频时长,默认 2 秒
1660
+
1661
+ ###### extend?
1662
+
1663
+ `boolean`
1664
+
1665
+ 模型是否自动优化提示词,默认为 false,但有些服务商可能无效
1666
+
1667
+ ###### imgs?
1668
+
1669
+ `string`[]
1670
+
1671
+ ###### mode?
1672
+
1673
+ `"frame"` \| `"text"` \| `"ref"`
1674
+
1675
+ 文本(默认)、首尾帧、参考图
1676
+
1677
+ ###### model
1678
+
1679
+ `string`
1680
+
1681
+ ###### negative?
1682
+
1683
+ `string`
1684
+
1685
+ 负面提示词,用于引导模型避免生成某些内容
1686
+
1687
+ ###### prompt
1688
+
1689
+ `string`
1690
+
1691
+ 提示词,参考类可用 [I1] 指代图片,如 `[I1] 看向 [I2]`
1692
+
1693
+ ###### ratio?
1694
+
1695
+ `"16:9"` \| `"9:16"` \| `"4:3"` \| `"3:4"` \| `"1:1"` \| `"21:9"`
1696
+
1697
+ 比例,默认 16:9
1698
+
1699
+ ###### resolution?
1700
+
1701
+ `"480p"` \| `"720p"` \| `"1080p"`
1702
+
1703
+ 分辨率,默认 720p
1704
+
1705
+ ###### seed?
1706
+
1707
+ `number`
1708
+
1709
+ 随机种子,默认为随机,范围 0 - 2147483647
1710
+
1711
+ ###### shot?
1712
+
1713
+ `"multi"` \| `"single"`
1714
+
1715
+ 镜头,默认单镜头 single
1716
+
1717
+ #### Returns
1718
+
1719
+ `Promise`\<`false` \| \{ `request`: `string`; `seed`: `number`; `status`: `"PENDING"` \| `"RUNNING"` \| `"SUCCEEDED"` \| `"FAILED"` \| `"CANCELED"` \| `"UNKNOWN"`; `task`: `string`; \}\>
1720
+
1531
1721
  lib/ai/enumerations/ESERVICE.md
1532
1722
  ---
1533
1723
 
@@ -1539,7 +1729,7 @@ lib/ai/enumerations/ESERVICE.md
1539
1729
 
1540
1730
  # Enumeration: ESERVICE
1541
1731
 
1542
- Defined in: [lib/ai.ts:18](https://github.com/maiyunnet/kebab/blob/master/lib/ai.ts#L18)
1732
+ Defined in: [lib/ai.ts:19](https://github.com/maiyunnet/kebab/blob/master/lib/ai.ts#L19)
1543
1733
 
1544
1734
  服务商定义
1545
1735
 
@@ -1549,7 +1739,7 @@ Defined in: [lib/ai.ts:18](https://github.com/maiyunnet/kebab/blob/master/lib/ai
1549
1739
 
1550
1740
  > **ALIAS**: `1`
1551
1741
 
1552
- Defined in: [lib/ai.ts:22](https://github.com/maiyunnet/kebab/blob/master/lib/ai.ts#L22)
1742
+ Defined in: [lib/ai.ts:23](https://github.com/maiyunnet/kebab/blob/master/lib/ai.ts#L23)
1553
1743
 
1554
1744
  阿里国际区
1555
1745
 
@@ -1559,7 +1749,7 @@ Defined in: [lib/ai.ts:22](https://github.com/maiyunnet/kebab/blob/master/lib/ai
1559
1749
 
1560
1750
  > **ALICN**: `0`
1561
1751
 
1562
- Defined in: [lib/ai.ts:20](https://github.com/maiyunnet/kebab/blob/master/lib/ai.ts#L20)
1752
+ Defined in: [lib/ai.ts:21](https://github.com/maiyunnet/kebab/blob/master/lib/ai.ts#L21)
1563
1753
 
1564
1754
  阿里中国大陆区
1565
1755
 
@@ -1569,7 +1759,7 @@ Defined in: [lib/ai.ts:20](https://github.com/maiyunnet/kebab/blob/master/lib/ai
1569
1759
 
1570
1760
  > **AZURE**: `2`
1571
1761
 
1572
- Defined in: [lib/ai.ts:24](https://github.com/maiyunnet/kebab/blob/master/lib/ai.ts#L24)
1762
+ Defined in: [lib/ai.ts:25](https://github.com/maiyunnet/kebab/blob/master/lib/ai.ts#L25)
1573
1763
 
1574
1764
  微软 Azure
1575
1765
 
@@ -1579,7 +1769,7 @@ Defined in: [lib/ai.ts:24](https://github.com/maiyunnet/kebab/blob/master/lib/ai
1579
1769
 
1580
1770
  > **AZURE2**: `3`
1581
1771
 
1582
- Defined in: [lib/ai.ts:26](https://github.com/maiyunnet/kebab/blob/master/lib/ai.ts#L26)
1772
+ Defined in: [lib/ai.ts:27](https://github.com/maiyunnet/kebab/blob/master/lib/ai.ts#L27)
1583
1773
 
1584
1774
  微软 Azure 2
1585
1775
 
@@ -1589,10 +1779,50 @@ Defined in: [lib/ai.ts:26](https://github.com/maiyunnet/kebab/blob/master/lib/ai
1589
1779
 
1590
1780
  > **AZURE3**: `4`
1591
1781
 
1592
- Defined in: [lib/ai.ts:28](https://github.com/maiyunnet/kebab/blob/master/lib/ai.ts#L28)
1782
+ Defined in: [lib/ai.ts:29](https://github.com/maiyunnet/kebab/blob/master/lib/ai.ts#L29)
1593
1783
 
1594
1784
  微软 Azure 3
1595
1785
 
1786
+ ***
1787
+
1788
+ ### GEMINI
1789
+
1790
+ > **GEMINI**: `5`
1791
+
1792
+ Defined in: [lib/ai.ts:31](https://github.com/maiyunnet/kebab/blob/master/lib/ai.ts#L31)
1793
+
1794
+ Gemini
1795
+
1796
+ ***
1797
+
1798
+ ### GROK
1799
+
1800
+ > **GROK**: `6`
1801
+
1802
+ Defined in: [lib/ai.ts:33](https://github.com/maiyunnet/kebab/blob/master/lib/ai.ts#L33)
1803
+
1804
+ Grok
1805
+
1806
+ ***
1807
+
1808
+ ### VOLAS
1809
+
1810
+ > **VOLAS**: `8`
1811
+
1812
+ Defined in: [lib/ai.ts:37](https://github.com/maiyunnet/kebab/blob/master/lib/ai.ts#L37)
1813
+
1814
+ 火山引擎国际区
1815
+
1816
+ ***
1817
+
1818
+ ### VOLCN
1819
+
1820
+ > **VOLCN**: `7`
1821
+
1822
+ Defined in: [lib/ai.ts:35](https://github.com/maiyunnet/kebab/blob/master/lib/ai.ts#L35)
1823
+
1824
+ 火山引擎中国大陆区
1825
+
1596
1826
  lib/ai/functions/get.md
1597
1827
  ---
1598
1828
 
@@ -1606,7 +1836,7 @@ lib/ai/functions/get.md
1606
1836
 
1607
1837
  > **get**(`ctrEtc`, `opt`): [`Ai`](../classes/Ai.md)
1608
1838
 
1609
- Defined in: [lib/ai.ts:154](https://github.com/maiyunnet/kebab/blob/master/lib/ai.ts#L154)
1839
+ Defined in: [lib/ai.ts:589](https://github.com/maiyunnet/kebab/blob/master/lib/ai.ts#L589)
1610
1840
 
1611
1841
  创建一个 AI 对象
1612
1842
 
@@ -1664,7 +1894,7 @@ lib/ai/interfaces/IOptions.md
1664
1894
 
1665
1895
  # Interface: IOptions
1666
1896
 
1667
- Defined in: [lib/ai.ts:32](https://github.com/maiyunnet/kebab/blob/master/lib/ai.ts#L32)
1897
+ Defined in: [lib/ai.ts:41](https://github.com/maiyunnet/kebab/blob/master/lib/ai.ts#L41)
1668
1898
 
1669
1899
  选项
1670
1900
 
@@ -1674,7 +1904,7 @@ Defined in: [lib/ai.ts:32](https://github.com/maiyunnet/kebab/blob/master/lib/ai
1674
1904
 
1675
1905
  > `optional` **endpoint**: `string`
1676
1906
 
1677
- Defined in: [lib/ai.ts:36](https://github.com/maiyunnet/kebab/blob/master/lib/ai.ts#L36)
1907
+ Defined in: [lib/ai.ts:45](https://github.com/maiyunnet/kebab/blob/master/lib/ai.ts#L45)
1678
1908
 
1679
1909
  接入点
1680
1910
 
@@ -1684,7 +1914,7 @@ Defined in: [lib/ai.ts:36](https://github.com/maiyunnet/kebab/blob/master/lib/ai
1684
1914
 
1685
1915
  > `optional` **fetch**: (`input`, `init?`) => `Promise`\<`Response`\>
1686
1916
 
1687
- Defined in: [lib/ai.ts:40](https://github.com/maiyunnet/kebab/blob/master/lib/ai.ts#L40)
1917
+ Defined in: [lib/ai.ts:49](https://github.com/maiyunnet/kebab/blob/master/lib/ai.ts#L49)
1688
1918
 
1689
1919
  自定义 fetch 函数
1690
1920
 
@@ -1708,7 +1938,7 @@ Defined in: [lib/ai.ts:40](https://github.com/maiyunnet/kebab/blob/master/lib/ai
1708
1938
 
1709
1939
  > `optional` **secretKey**: `string`
1710
1940
 
1711
- Defined in: [lib/ai.ts:38](https://github.com/maiyunnet/kebab/blob/master/lib/ai.ts#L38)
1941
+ Defined in: [lib/ai.ts:47](https://github.com/maiyunnet/kebab/blob/master/lib/ai.ts#L47)
1712
1942
 
1713
1943
  密钥
1714
1944
 
@@ -1718,7 +1948,7 @@ Defined in: [lib/ai.ts:38](https://github.com/maiyunnet/kebab/blob/master/lib/ai
1718
1948
 
1719
1949
  > **service**: [`ESERVICE`](../enumerations/ESERVICE.md)
1720
1950
 
1721
- Defined in: [lib/ai.ts:34](https://github.com/maiyunnet/kebab/blob/master/lib/ai.ts#L34)
1951
+ Defined in: [lib/ai.ts:43](https://github.com/maiyunnet/kebab/blob/master/lib/ai.ts#L43)
1722
1952
 
1723
1953
  服务商 -
1724
1954
 
package/index.d.ts CHANGED
@@ -5,7 +5,7 @@
5
5
  * --- 本文件用来定义每个目录实体地址的常量 ---
6
6
  */
7
7
  /** --- 当前系统版本号 --- */
8
- export declare const VER = "8.0.6";
8
+ export declare const VER = "8.1.0";
9
9
  /** --- 框架根目录,以 / 结尾 --- */
10
10
  export declare const ROOT_PATH: string;
11
11
  export declare const LIB_PATH: string;
package/index.js CHANGED
@@ -6,7 +6,7 @@
6
6
  * --- 本文件用来定义每个目录实体地址的常量 ---
7
7
  */
8
8
  /** --- 当前系统版本号 --- */
9
- export const VER = '8.0.6';
9
+ export const VER = '8.1.0';
10
10
  // --- 服务端用的路径 ---
11
11
  const imu = decodeURIComponent(import.meta.url).replace('file://', '').replace(/^\/(\w:)/, '$1');
12
12
  /** --- /xxx/xxx --- */
package/lib/ai.d.ts CHANGED
@@ -22,7 +22,15 @@ export declare enum ESERVICE {
22
22
  /** --- 微软 Azure 2 --- */
23
23
  'AZURE2' = 3,
24
24
  /** --- 微软 Azure 3 --- */
25
- 'AZURE3' = 4
25
+ 'AZURE3' = 4,
26
+ /** --- Gemini --- */
27
+ 'GEMINI' = 5,
28
+ /** --- Grok --- */
29
+ 'GROK' = 6,
30
+ /** --- 火山引擎中国大陆区 --- */
31
+ 'VOLCN' = 7,
32
+ /** --- 火山引擎国际区 --- */
33
+ 'VOLAS' = 8
26
34
  }
27
35
  /** --- 选项 --- */
28
36
  export interface IOptions {
@@ -36,16 +44,97 @@ export interface IOptions {
36
44
  'fetch'?: (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
37
45
  }
38
46
  export declare class Ai {
39
- /** --- openai 原生对象,建议只读 --- */
47
+ /** --- openai 原生对象 --- */
40
48
  readonly link: openai.OpenAI;
49
+ private readonly _fetch;
50
+ private readonly _service;
51
+ private readonly _endpoint;
41
52
  private readonly _ctr?;
42
53
  constructor(ctrEtc: sCtr.Ctr | kebab.IConfigAi, opt: IOptions);
54
+ /** --- 获取当前服务商 --- */
55
+ get service(): ESERVICE;
43
56
  /** --- 创建非流式对话 --- */
44
57
  chat(body: openai.default.Chat.Completions.ChatCompletionCreateParamsNonStreaming): Promise<openai.APIPromise<openai.default.Chat.ChatCompletion> | false>;
45
58
  /** --- 创建流式对话 --- */
46
59
  chat(body: openai.default.Chat.Completions.ChatCompletionCreateParamsStreaming): Promise<openai.APIPromise<streaming.Stream<openai.default.Chat.ChatCompletionChunk>> | false>;
47
60
  /** --- 创建向量 --- */
48
61
  embedding(body: openai.default.EmbeddingCreateParams): Promise<openai.APIPromise<openai.default.CreateEmbeddingResponse> | false>;
62
+ /** --- 生成图像,不支持 GEMINI、GROK 服务商 --- */
63
+ image(opt: {
64
+ 'model': string;
65
+ /** --- 提示词 --- */
66
+ 'prompt': string;
67
+ /** --- 参考图,请注意模型是否支持,以及是否支持多张,仅支持 ALICN、ALIAS、VOLCN、VOLAS 服务商 --- */
68
+ 'imgs'?: string[];
69
+ /** --- 模型是否自动优化提示词,默认为 false,但有些服务商可能无效 --- */
70
+ 'extend'?: boolean;
71
+ /** --- 负面提示词,用于引导模型避免生成某些内容 --- */
72
+ 'negative'?: string;
73
+ /** --- 长 x 宽,不同模型要求不同,如 [1664, 928] --- */
74
+ 'size': number[];
75
+ 'n'?: number;
76
+ /** --- 随机种子,默认为随机 --- */
77
+ 'seed'?: number;
78
+ }): Promise<{
79
+ /** --- 图像列表 --- */
80
+ 'list': Array<{
81
+ 'url': string;
82
+ /** --- 优化后的提示词 --- */
83
+ 'text': string;
84
+ }>;
85
+ /** --- 随机种子 --- */
86
+ 'seed': number;
87
+ /** --- 请求编号 --- */
88
+ 'request': string;
89
+ } | false>;
90
+ /** --- 异步生成视频,仅支持 ALICN、ALIAS --- */
91
+ video(opt: {
92
+ 'model': string;
93
+ /** --- 提示词,参考类可用 [I1] 指代图片,如 `[I1] 看向 [I2]` --- */
94
+ 'prompt': string;
95
+ /** --- 文本(默认)、首尾帧、参考图 --- */
96
+ 'mode'?: 'text' | 'frame' | 'ref';
97
+ 'imgs'?: string[];
98
+ /** --- 负面提示词,用于引导模型避免生成某些内容 --- */
99
+ 'negative'?: string;
100
+ /** --- 模型是否自动优化提示词,默认为 false,但有些服务商可能无效 --- */
101
+ 'extend'?: boolean;
102
+ /** --- 分辨率,默认 720p --- */
103
+ 'resolution'?: '480p' | '720p' | '1080p';
104
+ /** --- 比例,默认 16:9 --- */
105
+ 'ratio'?: '16:9' | '9:16' | '4:3' | '3:4' | '1:1' | '21:9';
106
+ /** --- 视频时长,默认 2 秒 --- */
107
+ 'duration'?: number;
108
+ /** --- 镜头,默认单镜头 single --- */
109
+ 'shot'?: 'single' | 'multi';
110
+ /** --- 视频声音,默认 false,true 代表自动配音,字符串代表自定义音频网址 --- */
111
+ 'audio'?: boolean | string;
112
+ /** --- 随机种子,默认为随机,范围 0 - 2147483647 --- */
113
+ 'seed'?: number;
114
+ }): Promise<{
115
+ 'task': string;
116
+ 'status': 'PENDING' | 'RUNNING' | 'SUCCEEDED' | 'FAILED' | 'CANCELED' | 'UNKNOWN';
117
+ 'seed': number;
118
+ 'request': string;
119
+ } | false>;
120
+ /** --- 轮询任务 --- */
121
+ poll(opt: {
122
+ 'type': 'video';
123
+ 'task': string;
124
+ }): Promise<{
125
+ 'task': string;
126
+ 'status': 'PENDING' | 'RUNNING' | 'SUCCEEDED' | 'FAILED' | 'CANCELED' | 'UNKNOWN';
127
+ /** --- 任务提交时间 --- */
128
+ 'add'?: number;
129
+ /** --- 任务开始时间 --- */
130
+ 'start'?: number;
131
+ /** --- 任务结束时间 --- */
132
+ 'end'?: number;
133
+ /** --- 文件地址 --- */
134
+ 'url'?: string;
135
+ /** --- 错误信息,成功时不返回 --- */
136
+ 'error'?: string;
137
+ } | false>;
49
138
  }
50
139
  /**
51
140
  * --- 创建一个 AI 对象 ---
package/lib/ai.js CHANGED
@@ -5,6 +5,7 @@
5
5
  */
6
6
  import * as openai from 'openai';
7
7
  import * as lCore from '#kebab/lib/core.js';
8
+ import * as lText from '#kebab/lib/text.js';
8
9
  import * as sCtr from '#kebab/sys/ctr.js';
9
10
  /**
10
11
  * --- 参考:https://help.aliyun.com/zh/model-studio/what-is-model-studio ---
@@ -23,12 +24,23 @@ export var ESERVICE;
23
24
  ESERVICE[ESERVICE["AZURE2"] = 3] = "AZURE2";
24
25
  /** --- 微软 Azure 3 --- */
25
26
  ESERVICE[ESERVICE["AZURE3"] = 4] = "AZURE3";
27
+ /** --- Gemini --- */
28
+ ESERVICE[ESERVICE["GEMINI"] = 5] = "GEMINI";
29
+ /** --- Grok --- */
30
+ ESERVICE[ESERVICE["GROK"] = 6] = "GROK";
31
+ /** --- 火山引擎中国大陆区 --- */
32
+ ESERVICE[ESERVICE["VOLCN"] = 7] = "VOLCN";
33
+ /** --- 火山引擎国际区 --- */
34
+ ESERVICE[ESERVICE["VOLAS"] = 8] = "VOLAS";
26
35
  })(ESERVICE || (ESERVICE = {}));
27
36
  /** --- openai 的连接对象 --- */
28
37
  const links = [];
29
38
  export class Ai {
30
- /** --- openai 原生对象,建议只读 --- */
39
+ /** --- openai 原生对象 --- */
31
40
  link;
41
+ _fetch;
42
+ _service;
43
+ _endpoint;
32
44
  _ctr;
33
45
  constructor(ctrEtc, opt) {
34
46
  let configAi = null;
@@ -41,6 +53,7 @@ export class Ai {
41
53
  configAi = ctrEtc;
42
54
  }
43
55
  const secretKey = opt.secretKey ?? configAi.skey ?? '';
56
+ const token = `${opt.service}-${secretKey}`;
44
57
  let endpoint;
45
58
  switch (opt.service) {
46
59
  case ESERVICE.ALICN: {
@@ -59,16 +72,32 @@ export class Ai {
59
72
  endpoint = opt.endpoint ?? configAi.endpoint ?? '';
60
73
  break;
61
74
  }
62
- case ESERVICE.AZURE3: {
63
- endpoint = opt.endpoint ?? configAi.endpoint ?? '';
75
+ case ESERVICE.GEMINI: {
76
+ endpoint = opt.endpoint ?? `https://generativelanguage.googleapis.com/v1beta/openai/`;
77
+ break;
78
+ }
79
+ case ESERVICE.GROK: {
80
+ endpoint = opt.endpoint ?? `https://api.x.ai/v1`;
81
+ break;
82
+ }
83
+ case ESERVICE.VOLCN: {
84
+ endpoint = opt.endpoint ?? `https://ark.cn-beijing.volces.com/api/v3`;
85
+ break;
86
+ }
87
+ case ESERVICE.VOLAS: {
88
+ endpoint = opt.endpoint ?? `https://ark.ap-southeast.bytepluses.com/api/v3`;
64
89
  break;
65
90
  }
66
91
  default: {
67
- endpoint = undefined;
92
+ // --- ESERVICE.AZURE3 ---
93
+ endpoint = opt.endpoint ?? configAi.endpoint ?? '';
68
94
  }
69
95
  }
70
- const token = `${opt.service}-${secretKey}`;
71
- const link = links.find((item) => item.token === token);
96
+ this._fetch = opt.fetch ?? fetch;
97
+ this._service = opt.service;
98
+ this._endpoint = endpoint;
99
+ // --- 处理连接 ---
100
+ const link = links.find(item => item.token === token);
72
101
  if (link) {
73
102
  this.link = link.link;
74
103
  return;
@@ -83,6 +112,10 @@ export class Ai {
83
112
  'link': this.link,
84
113
  });
85
114
  }
115
+ /** --- 获取当前服务商 --- */
116
+ get service() {
117
+ return this._service;
118
+ }
86
119
  /** --- 创建对话 --- */
87
120
  async chat(body) {
88
121
  try {
@@ -105,6 +138,327 @@ export class Ai {
105
138
  return false;
106
139
  }
107
140
  }
141
+ /** --- 生成图像,不支持 GEMINI、GROK 服务商 --- */
142
+ async image(opt) {
143
+ const seed = opt.seed ?? lCore.rand(0, 2147483647);
144
+ switch (this._service) {
145
+ case ESERVICE.ALICN:
146
+ case ESERVICE.ALIAS: {
147
+ try {
148
+ const res = await this._fetch(`https://dashscope${this._service === ESERVICE.ALIAS ? '-intl' : ''}.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation`, {
149
+ 'method': 'POST',
150
+ 'headers': {
151
+ 'authorization': `Bearer ${this.link.apiKey}`,
152
+ 'content-type': 'application/json',
153
+ },
154
+ 'body': lText.stringifyJson({
155
+ 'model': opt.model,
156
+ 'input': {
157
+ 'messages': [
158
+ {
159
+ 'role': 'user',
160
+ 'content': [
161
+ ...(opt.imgs?.map(url => ({
162
+ 'image': url,
163
+ })) ?? []),
164
+ {
165
+ 'text': opt.prompt,
166
+ }
167
+ ]
168
+ }
169
+ ]
170
+ },
171
+ 'parameters': {
172
+ 'negative_prompt': opt.negative ?? ' ',
173
+ 'prompt_extend': opt.extend ?? false,
174
+ 'watermark': false,
175
+ 'size': `${opt.size[0]}*${opt.size[1]}`,
176
+ 'n': opt.n ?? 1,
177
+ 'seed': seed,
178
+ },
179
+ }),
180
+ });
181
+ const json = await res.json();
182
+ if (!json.output?.choices?.[0]) {
183
+ lCore.debug('[AI][IMAGE]', json);
184
+ lCore.log(this._ctr ?? {}, `[AI][IMAGE] ${lText.stringifyJson(json)}`, '-error');
185
+ return false;
186
+ }
187
+ return {
188
+ 'list': json.output.choices[0].message.content.filter((item) => item.image).map((item) => {
189
+ const content = json.output.choices[0].message.content;
190
+ const itemIndex = content.indexOf(item);
191
+ return {
192
+ 'url': item.image,
193
+ 'text': content[itemIndex + 1]?.text ?? '',
194
+ };
195
+ }),
196
+ 'seed': seed,
197
+ 'request': json.request_id,
198
+ };
199
+ }
200
+ catch (e) {
201
+ lCore.debug('[AI][IMAGE]', e);
202
+ lCore.log(this._ctr ?? {}, `[AI][IMAGE] ${e.message}`, '-error');
203
+ return false;
204
+ }
205
+ }
206
+ case ESERVICE.AZURE:
207
+ case ESERVICE.AZURE2:
208
+ case ESERVICE.AZURE3: {
209
+ try {
210
+ const json = await this.link.images.generate({
211
+ 'model': opt.model,
212
+ 'prompt': opt.prompt,
213
+ 'size': `${opt.size[0]}x${opt.size[1]}`,
214
+ 'n': opt.n ?? 1,
215
+ });
216
+ if (!json.data?.[0]) {
217
+ lCore.debug('[AI][IMAGE]', json);
218
+ lCore.log(this._ctr ?? {}, `[AI][IMAGE] ${lText.stringifyJson(json)}`, '-error');
219
+ return false;
220
+ }
221
+ return {
222
+ 'list': json.data.map((item) => ({
223
+ 'url': item.url ?? item.b64_json,
224
+ 'text': item.revised_prompt ?? opt.prompt,
225
+ })),
226
+ 'seed': seed,
227
+ 'request': json.created.toString(),
228
+ };
229
+ }
230
+ catch (e) {
231
+ lCore.debug('[AI][IMAGE]', e);
232
+ lCore.log(this._ctr ?? {}, `[AI][IMAGE] ${e.message}`, '-error');
233
+ return false;
234
+ }
235
+ }
236
+ case ESERVICE.GEMINI: {
237
+ return false;
238
+ }
239
+ case ESERVICE.GROK: {
240
+ return false;
241
+ }
242
+ case ESERVICE.VOLCN:
243
+ case ESERVICE.VOLAS: {
244
+ try {
245
+ const res = await this._fetch(`${this._endpoint}/images/generations`, {
246
+ 'method': 'POST',
247
+ 'headers': {
248
+ 'authorization': `Bearer ${this.link.apiKey}`,
249
+ 'content-type': 'application/json',
250
+ },
251
+ 'body': lText.stringifyJson({
252
+ 'model': opt.model,
253
+ 'prompt': opt.prompt,
254
+ 'watermark': false,
255
+ 'size': `${opt.size[0]}x${opt.size[1]}`,
256
+ 'seed': seed,
257
+ ...(opt.n && opt.n > 1 ? {
258
+ 'sequential_image_generation': 'auto',
259
+ 'sequential_image_generation_options': {
260
+ 'max_images': 4,
261
+ },
262
+ } : {
263
+ 'sequential_image_generation': 'disabled',
264
+ }),
265
+ ...(opt.imgs?.length ? {
266
+ 'image': opt.imgs.length === 1 ? opt.imgs[0] : opt.imgs,
267
+ } : {}),
268
+ }),
269
+ });
270
+ const json = await res.json();
271
+ if (!json.data?.[0]) {
272
+ lCore.debug('[AI][IMAGE]', json);
273
+ lCore.log(this._ctr ?? {}, `[AI][IMAGE] ${lText.stringifyJson(json)}`, '-error');
274
+ return false;
275
+ }
276
+ return {
277
+ 'list': json.data.map((item) => ({
278
+ 'url': item.url,
279
+ 'text': opt.prompt,
280
+ })),
281
+ 'seed': seed,
282
+ 'request': json.created.toString(),
283
+ };
284
+ }
285
+ catch (e) {
286
+ lCore.debug('[AI][IMAGE]', e);
287
+ lCore.log(this._ctr ?? {}, `[AI][IMAGE] ${e.message}`, '-error');
288
+ return false;
289
+ }
290
+ }
291
+ }
292
+ }
293
+ /** --- 异步生成视频,仅支持 ALICN、ALIAS --- */
294
+ async video(opt) {
295
+ if (this._service !== ESERVICE.ALICN && this._service !== ESERVICE.ALIAS) {
296
+ return false;
297
+ }
298
+ const mode = opt.mode ?? 'text';
299
+ const imgs = opt.imgs ?? [];
300
+ const resolution = opt.resolution ?? '720p';
301
+ const ratio = opt.ratio ?? '16:9';
302
+ const duration = opt.duration ?? 2;
303
+ const shot = opt.shot ?? 'single';
304
+ const audio = opt.audio ?? false;
305
+ const seed = opt.seed ?? lCore.rand(0, 2147483647);
306
+ const extend = opt.extend ?? false;
307
+ /** --- x*x --- */
308
+ let size = '';
309
+ if (resolution === '480p') {
310
+ // --- 不支持 ---
311
+ return false;
312
+ }
313
+ else if (resolution === '720p') {
314
+ switch (ratio) {
315
+ case '21:9': {
316
+ // --- 不支持 ---
317
+ return false;
318
+ }
319
+ case '16:9': {
320
+ size = '1280*720';
321
+ break;
322
+ }
323
+ case '9:16': {
324
+ size = '720*1280';
325
+ break;
326
+ }
327
+ case '4:3': {
328
+ size = '1088*832';
329
+ break;
330
+ }
331
+ case '3:4': {
332
+ size = '832*1088';
333
+ break;
334
+ }
335
+ default: {
336
+ // --- 1:1 ---
337
+ size = '960*960';
338
+ }
339
+ }
340
+ }
341
+ else {
342
+ // --- 1080p ---
343
+ switch (ratio) {
344
+ case '21:9': {
345
+ // --- 不支持 ---
346
+ return false;
347
+ }
348
+ case '16:9': {
349
+ size = '1920*1080';
350
+ break;
351
+ }
352
+ case '9:16': {
353
+ size = '1080*1920';
354
+ break;
355
+ }
356
+ case '4:3': {
357
+ size = '1632*1248';
358
+ break;
359
+ }
360
+ case '3:4': {
361
+ size = '1248*1632';
362
+ break;
363
+ }
364
+ default: {
365
+ // --- 1:1 ---
366
+ size = '1440*1440';
367
+ }
368
+ }
369
+ }
370
+ try {
371
+ const res = await this._fetch(`https://dashscope${this._service === ESERVICE.ALIAS ? '-intl' : ''}.aliyuncs.com/api/v1/services/aigc/video-generation/video-synthesis`, {
372
+ 'method': 'POST',
373
+ 'headers': {
374
+ 'authorization': `Bearer ${this.link.apiKey}`,
375
+ 'content-type': 'application/json',
376
+ 'X-DashScope-Async': 'enable',
377
+ },
378
+ 'body': lText.stringifyJson({
379
+ 'model': opt.model,
380
+ 'input': {
381
+ 'prompt': opt.prompt.replace(/\[I(\d+)\]/g, 'Character$1'),
382
+ ...(typeof audio === 'string' ? {
383
+ 'audio_url': audio,
384
+ } : {})
385
+ },
386
+ 'parameters': {
387
+ 'negative_prompt': opt.negative ?? ' ',
388
+ 'watermark': false,
389
+ 'size': size,
390
+ 'seed': seed,
391
+ 'audio': audio ? true : false,
392
+ 'duration': duration,
393
+ 'shot_type': shot,
394
+ 'prompt_extend': extend,
395
+ ...((mode !== 'text') && (mode === 'frame' ? (imgs.length > 1 ? {
396
+ // --- 首尾帧 ---
397
+ 'first_frame_url': imgs[0],
398
+ 'last_frame_url': imgs[1],
399
+ } : {
400
+ // --- 首帧 ---
401
+ 'img_url': imgs[0],
402
+ }) : {
403
+ 'reference_urls': imgs,
404
+ })),
405
+ },
406
+ }),
407
+ });
408
+ const json = await res.json();
409
+ if (!json.output?.task_id) {
410
+ lCore.debug('[AI][VIDEO]', json);
411
+ lCore.log(this._ctr ?? {}, `[AI][VIDEO] ${lText.stringifyJson(json)}`, '-error');
412
+ return false;
413
+ }
414
+ const task = json.output.task_id;
415
+ return {
416
+ 'task': task,
417
+ 'status': json.output.task_status,
418
+ 'seed': seed,
419
+ 'request': json.request_id,
420
+ };
421
+ }
422
+ catch (e) {
423
+ lCore.debug('[AI][VIDEO]', e);
424
+ lCore.log(this._ctr ?? {}, `[AI][VIDEO] ${e.message}`, '-error');
425
+ return false;
426
+ }
427
+ }
428
+ /** --- 轮询任务 --- */
429
+ async poll(opt) {
430
+ if (this._service !== ESERVICE.ALICN && this._service !== ESERVICE.ALIAS) {
431
+ return false;
432
+ }
433
+ try {
434
+ const res = await this._fetch(`https://dashscope${this._service === ESERVICE.ALIAS ? '-intl' : ''}.aliyuncs.com/api/v1/tasks/${opt.task}`, {
435
+ 'method': 'GET',
436
+ 'headers': {
437
+ 'authorization': `Bearer ${this.link.apiKey}`,
438
+ },
439
+ });
440
+ const json = await res.json();
441
+ if (!json.output?.task_status) {
442
+ lCore.debug('[AI][POLL]', json);
443
+ lCore.log(this._ctr ?? {}, `[AI][POLL] ${lText.stringifyJson(json)}`, '-error');
444
+ return false;
445
+ }
446
+ return {
447
+ 'task': json.output.task_id,
448
+ 'status': json.output.task_status,
449
+ 'add': json.output.submit_time,
450
+ 'start': json.output.scheduled_time,
451
+ 'end': json.output.end_time,
452
+ 'url': json.output.video_url,
453
+ 'error': json.output.message ? `(${json.output.code})${json.output.message}` : undefined,
454
+ };
455
+ }
456
+ catch (e) {
457
+ lCore.debug('[AI][POLL]', e);
458
+ lCore.log(this._ctr ?? {}, `[AI][POLL] ${e.message}`, '-error');
459
+ return false;
460
+ }
461
+ }
108
462
  }
109
463
  /**
110
464
  * --- 创建一个 AI 对象 ---
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maiyunnet/kebab",
3
- "version": "8.0.6",
3
+ "version": "8.1.0",
4
4
  "description": "Simple, easy-to-use, and fully-featured Node.js framework that is ready-to-use out of the box.",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -22,30 +22,30 @@
22
22
  "#kebab/*": "./*"
23
23
  },
24
24
  "dependencies": {
25
- "@aws-sdk/client-s3": "^3.985.0",
26
- "@aws-sdk/lib-storage": "^3.985.0",
25
+ "@aws-sdk/client-s3": "^3.992.0",
26
+ "@aws-sdk/lib-storage": "^3.992.0",
27
27
  "@litert/http-client": "^1.1.2",
28
28
  "@litert/mime": "^0.1.3",
29
29
  "@litert/redis": "^3.1.0",
30
30
  "@litert/websocket": "^0.2.8",
31
31
  "@types/ssh2": "^1.15.5",
32
- "@zilliz/milvus2-sdk-node": "^2.6.9",
32
+ "@zilliz/milvus2-sdk-node": "^2.6.10",
33
33
  "ejs": "^4.0.1",
34
34
  "jszip": "^3.10.1",
35
- "mysql2": "^3.16.3",
35
+ "mysql2": "^3.17.2",
36
36
  "node-cron": "^4.2.1",
37
- "openai": "^6.18.0",
37
+ "openai": "^6.22.0",
38
38
  "pg": "^8.18.0",
39
39
  "ssh2": "^1.17.0",
40
40
  "svg-captcha": "^1.4.0",
41
- "tencentcloud-sdk-nodejs": "^4.1.185"
41
+ "tencentcloud-sdk-nodejs": "^4.1.186"
42
42
  },
43
43
  "devDependencies": {
44
44
  "@litert/eslint-plugin-rules": "^0.3.1",
45
45
  "@types/ejs": "^3.1.5",
46
- "@types/node": "^25.2.2",
46
+ "@types/node": "^25.2.3",
47
47
  "@types/pg": "^8.16.0",
48
- "typedoc": "^0.28.16",
48
+ "typedoc": "^0.28.17",
49
49
  "typedoc-plugin-markdown": "^4.10.0",
50
50
  "typescript": "^5.9.3"
51
51
  }
package/sys/cmd.js CHANGED
@@ -177,6 +177,14 @@ async function run() {
177
177
  config.ai['AZURE3'] ??= {};
178
178
  config.ai['AZURE3'].endpoint ??= '';
179
179
  config.ai['AZURE3'].skey ??= '';
180
+ config.ai['GEMINI'] ??= {};
181
+ config.ai['GEMINI'].skey ??= '';
182
+ config.ai['GROK'] ??= {};
183
+ config.ai['GROK'].skey ??= '';
184
+ config.ai['VOLCN'] ??= {};
185
+ config.ai['VOLCN'].skey ??= '';
186
+ config.ai['VOLAS'] ??= {};
187
+ config.ai['VOLAS'].skey ??= '';
180
188
  // --- config - vector ---
181
189
  config.vector ??= {};
182
190
  config.vector.host ??= '127.0.0.1';
@@ -127,8 +127,12 @@ export default class extends sCtr.Ctr {
127
127
  `<br><a href="${this._config.const.urlBase}test/mod-update-list">View "test/mod-update-list"</a>`,
128
128
  '<br><br><b>Library test:</b>',
129
129
  `<br><br><b>Ai:</b>`,
130
- `<br><br><a href="${this._config.const.urlBase}test/ai">View "test/ai"</a>`,
131
130
  `<br><a href="${this._config.const.urlBase}test/ai-stream">View "test/ai-stream"</a>`,
131
+ `<br><a href="${this._config.const.urlBase}test/ai?action=chat">View "test/ai?action=chat"</a>`,
132
+ `<br><a href="${this._config.const.urlBase}test/ai?action=text-to-image">View "test/ai?action=text-to-image"</a>`,
133
+ `<br><a href="${this._config.const.urlBase}test/ai?action=image-to-image">View "test/ai?action=image-to-image"</a>`,
134
+ `<br><a href="${this._config.const.urlBase}test/ai?action=text-to-video">View "test/ai?action=text-to-video"</a>`,
135
+ `<br><a href="${this._config.const.urlBase}test/ai?action=image-to-video">View "test/ai?action=image-to-video"</a>`,
132
136
  '<br><br><b>Core:</b>',
133
137
  `<br><br><a href="${this._config.const.urlBase}test/core-random">View "test/core-random"</a>`,
134
138
  `<br><a href="${this._config.const.urlBase}test/core-rand">View "test/core-rand"</a>`,
@@ -3337,31 +3341,177 @@ rtn.push(reader.readBCDString());</pre>${JSON.stringify(rtn)}`);
3337
3341
  return echo.join('') + '<br>' + this._getEnd();
3338
3342
  }
3339
3343
  async ai() {
3340
- const ai = lAi.get(this, {
3341
- 'service': lAi.ESERVICE.ALICN,
3342
- });
3343
3344
  const echo = [`<pre>const ai = lAi.get(this, {
3344
- 'service': lAi.ESERVICE.ALICN,
3345
+ 'service': lAi.ESERVICE.${lText.htmlescape(this._get['service']?.toUpperCase() ?? 'ALICN')},
3345
3346
  });</pre>`];
3346
- const completion = await ai.chat({
3347
- 'model': 'qwen-plus',
3348
- 'messages': [
3349
- { 'role': 'system', 'content': 'You are Kebab, a friendly and knowledgeable assistant based on an open-source Node framework. You do not mention any model names or AI identity. You can chat casually, answer questions, and provide guidance naturally. Respond in a human-like, approachable manner, as if you are a helpful companion rather than a traditional AI assistant.' },
3350
- { 'role': 'user', 'content': '你是谁?' },
3351
- ],
3347
+ const ai = lAi.get(this, {
3348
+ 'service': lAi.ESERVICE[this._get['service']?.toUpperCase() ?? 'ALICN'] ?? lAi.ESERVICE.ALICN,
3352
3349
  });
3353
- echo.push(`<pre>await ai.chat({
3354
- 'model': 'qwen-plus',
3350
+ switch (this._get['action']) {
3351
+ case 'text-to-image': {
3352
+ // --- 文生图 ---
3353
+ let model = 'z-image-turbo';
3354
+ let size = [1280, 720];
3355
+ if (ai.service !== lAi.ESERVICE.ALICN && ai.service !== lAi.ESERVICE.ALIAS) {
3356
+ switch (ai.service) {
3357
+ case lAi.ESERVICE.AZURE:
3358
+ case lAi.ESERVICE.AZURE2:
3359
+ case lAi.ESERVICE.AZURE3: {
3360
+ model = 'FLUX.2-pro';
3361
+ break;
3362
+ }
3363
+ default: {
3364
+ // --- 火山引擎 ---
3365
+ model = 'doubao-seedream-4-5-251128';
3366
+ size = [2560, 1440];
3367
+ }
3368
+ }
3369
+ }
3370
+ const imgResult = await ai.image({
3371
+ 'model': model,
3372
+ 'prompt': 'A cute cat sitting on a windowsill watching the sunset',
3373
+ 'size': size,
3374
+ 'n': 1,
3375
+ });
3376
+ echo.push(`<pre>await ai.image({
3377
+ 'model': '${model}',
3378
+ 'prompt': 'A cute cat sitting on a windowsill watching the sunset',
3379
+ 'size': [${size[0]}, ${size[1]}],
3380
+ 'n': 1,
3381
+ });</pre>`);
3382
+ if (imgResult && imgResult.list?.length) {
3383
+ for (const img of imgResult.list) {
3384
+ echo.push(`<div><img src="${img.url.startsWith('http') ? img.url : 'data:image/png;base64,' + img.url}" style="max-width: 512px;" /></div>${lText.htmlescape(img.text)}`);
3385
+ }
3386
+ echo.push('<br>request: ' + imgResult.request, ', seed: ' + imgResult.seed);
3387
+ }
3388
+ else {
3389
+ echo.push('Failed');
3390
+ }
3391
+ break;
3392
+ }
3393
+ case 'image-to-image': {
3394
+ // --- 图生图 ---
3395
+ let model = 'wan2.6-image';
3396
+ let size = [1280, 720];
3397
+ const prompt = '用图1的绘画风格重绘图2的场景,桌上增加一盘番茄炒蛋';
3398
+ if (ai.service !== lAi.ESERVICE.ALICN && ai.service !== lAi.ESERVICE.ALIAS) {
3399
+ switch (ai.service) {
3400
+ default: {
3401
+ // --- 火山引擎 ---
3402
+ model = 'doubao-seedream-4-5-251128';
3403
+ size = [2560, 1440];
3404
+ }
3405
+ }
3406
+ }
3407
+ const imgResult = await ai.image({
3408
+ 'model': model,
3409
+ 'imgs': [
3410
+ 'https://cdn.wanx.aliyuncs.com/tmp/pressure/umbrella1.png',
3411
+ 'https://img.alicdn.com/imgextra/i3/O1CN01SfG4J41UYn9WNt4X1_!!6000000002530-49-tps-1696-960.webp',
3412
+ ],
3413
+ 'prompt': prompt,
3414
+ 'size': size,
3415
+ 'n': 1,
3416
+ });
3417
+ echo.push(`<pre>await ai.image({
3418
+ 'model': '${model}',
3419
+ 'imgs': [
3420
+ 'https://cdn.wanx.aliyuncs.com/tmp/pressure/umbrella1.png',
3421
+ 'https://img.alicdn.com/imgextra/i3/O1CN01SfG4J41UYn9WNt4X1_!!6000000002530-49-tps-1696-960.webp',
3422
+ ],
3423
+ 'prompt': '${prompt}',
3424
+ 'size': [${size[0]}, ${size[1]}],
3425
+ 'n': 1,
3426
+ });</pre>`);
3427
+ if (imgResult && imgResult.list?.length) {
3428
+ echo.push(`<div>Reference Images:</div><div>
3429
+ <img src="https://cdn.wanx.aliyuncs.com/tmp/pressure/umbrella1.png" style="max-width: 256px; margin-right: 5px;" />
3430
+ <img src="https://img.alicdn.com/imgextra/i3/O1CN01SfG4J41UYn9WNt4X1_!!6000000002530-49-tps-1696-960.webp" style="max-width: 256px;" />
3431
+ </div>`);
3432
+ for (const img of imgResult.list) {
3433
+ echo.push(`<div><img src="${img.url.startsWith('http') ? img.url : 'data:image/png;base64,' + img.url}" style="max-width: 512px;" /></div>${lText.htmlescape(img.text || prompt)}`);
3434
+ }
3435
+ echo.push('<br>request: ' + imgResult.request, ', seed: ' + imgResult.seed);
3436
+ }
3437
+ else {
3438
+ echo.push('Failed');
3439
+ }
3440
+ break;
3441
+ }
3442
+ case 'text-to-video': {
3443
+ // --- 文生视频 ---
3444
+ const model = 'wan2.6-t2v';
3445
+ const vidResult = await ai.video({
3446
+ 'prompt': 'A cat playing with a ball of yarn',
3447
+ 'model': model,
3448
+ });
3449
+ echo.push(`<pre>await aiVid.video({
3450
+ 'prompt': 'A cat playing with a ball of yarn',
3451
+ 'model': '${model}',
3452
+ });</pre>`);
3453
+ if (vidResult) {
3454
+ echo.push(`<pre>${JSON.stringify(vidResult, null, 4)}</pre><a href="${this._config.const.urlBase}test/ai?action=video-poll&task=${vidResult.task}">poll</a>`);
3455
+ }
3456
+ else {
3457
+ echo.push('Failed');
3458
+ }
3459
+ break;
3460
+ }
3461
+ case 'image-to-video': {
3462
+ // --- 图生视频 ---
3463
+ echo.push('Not yet implemented');
3464
+ break;
3465
+ }
3466
+ case 'video-poll': {
3467
+ // --- 视频生成轮询 ---
3468
+ if (!this._get['task']) {
3469
+ echo.push('Task ID not found.');
3470
+ break;
3471
+ }
3472
+ const pollResult = await ai.poll({
3473
+ 'type': 'video',
3474
+ 'task': this._get['task'],
3475
+ });
3476
+ echo.push(`<pre>await ai.poll({
3477
+ 'type': 'video',
3478
+ 'task': '${this._get['task']}',
3479
+ });</pre>`);
3480
+ if (pollResult) {
3481
+ echo.push(`<pre>${JSON.stringify(pollResult, null, 4)}</pre>Result.`);
3482
+ }
3483
+ else {
3484
+ echo.push('Failed');
3485
+ }
3486
+ break;
3487
+ }
3488
+ default: {
3489
+ // --- CHAT ---
3490
+ let model = ai.service === lAi.ESERVICE.ALICN ? 'qwen-plus' : 'doubao-seed-2-0-mini-260215';
3491
+ if (ai.service === lAi.ESERVICE.AZURE) {
3492
+ model = 'gpt-4.1-nano';
3493
+ }
3494
+ const completion = await ai.chat({
3495
+ 'model': model,
3496
+ 'messages': [
3497
+ { 'role': 'system', 'content': 'You are Kebab, a friendly and knowledgeable assistant based on an open-source Node framework. You do not mention any model names or AI identity. You can chat casually, answer questions, and provide guidance naturally. Respond in a human-like, approachable manner, as if you are a helpful companion rather than a traditional AI assistant.' },
3498
+ { 'role': 'user', 'content': '你是谁?' },
3499
+ ],
3500
+ });
3501
+ echo.push(`<pre>await ai.chat({
3502
+ 'model': ${model},
3355
3503
  'messages': [
3356
3504
  { 'role': 'system', 'content': 'You are Kebab, a friendly and knowledgeable assistant based on an open-source Node framework. You do not mention any model names or AI identity. You can chat casually, answer questions, and provide guidance naturally. Respond in a human-like, approachable manner, as if you are a helpful companion rather than a traditional AI assistant.' },
3357
3505
  { 'role': 'user', 'content': '你是谁?' },
3358
3506
  ],
3359
3507
  });</pre>`);
3360
- if (completion) {
3361
- echo.push(JSON.stringify(completion.choices[0].message.content));
3362
- }
3363
- else {
3364
- echo.push('Failed');
3508
+ if (completion) {
3509
+ echo.push(JSON.stringify(completion.choices[0].message.content));
3510
+ }
3511
+ else {
3512
+ echo.push('Failed');
3513
+ }
3514
+ }
3365
3515
  }
3366
3516
  return echo.join('') + '<br><br>' + this._getEnd();
3367
3517
  }