@cloudbase/ai 4.0.0 → 4.0.1-alpha.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/.eslintrc.js +1 -0
- package/CHANGELOG.md +1164 -0
- package/dist/cjs/AI.d.ts +6 -3
- package/dist/cjs/AI.js +67 -24
- package/dist/cjs/bot/index.js +1 -1
- package/dist/cjs/errors.d.ts +10 -0
- package/dist/cjs/errors.js +38 -0
- package/dist/cjs/index.d.ts +7 -3
- package/dist/cjs/index.js +22 -8
- package/dist/cjs/models/Ark/index.js +1 -1
- package/dist/cjs/models/DashScope/index.js +1 -1
- package/dist/cjs/models/DeepSeek/index.js +1 -1
- package/dist/cjs/models/Default/index.js +1 -1
- package/dist/cjs/models/HunYuan/index.js +1 -1
- package/dist/cjs/models/HunYuan/util.js +1 -1
- package/dist/cjs/models/HunYuanBeta/index.js +1 -1
- package/dist/cjs/models/HunYuanExp/index.js +1 -1
- package/dist/cjs/models/HunYuanOpen/index.js +1 -1
- package/dist/cjs/models/Moonshot/index.js +1 -1
- package/dist/cjs/models/Yi/index.js +1 -1
- package/dist/cjs/models/ZhiPu/index.js +1 -1
- package/dist/cjs/models/image-model.d.ts +19 -0
- package/dist/cjs/models/image-model.js +106 -0
- package/dist/cjs/models/index.d.ts +2 -1
- package/dist/cjs/models/index.js +4 -2
- package/dist/cjs/models/model.js +1 -1
- package/dist/cjs/type.d.ts +81 -0
- package/dist/cjs/type.js +1 -1
- package/dist/cjs/utils.d.ts +1 -1
- package/dist/cjs/utils.js +9 -4
- package/dist/esm/AI.d.ts +6 -3
- package/dist/esm/AI.js +67 -24
- package/dist/esm/bot/index.js +1 -1
- package/dist/esm/errors.d.ts +10 -0
- package/dist/esm/errors.js +35 -0
- package/dist/esm/index.d.ts +7 -3
- package/dist/esm/index.js +21 -8
- package/dist/esm/models/Ark/index.js +1 -1
- package/dist/esm/models/DashScope/index.js +1 -1
- package/dist/esm/models/DeepSeek/index.js +1 -1
- package/dist/esm/models/Default/index.js +1 -1
- package/dist/esm/models/HunYuan/index.js +1 -1
- package/dist/esm/models/HunYuan/util.js +1 -1
- package/dist/esm/models/HunYuanBeta/index.js +1 -1
- package/dist/esm/models/HunYuanExp/index.js +1 -1
- package/dist/esm/models/HunYuanOpen/index.js +1 -1
- package/dist/esm/models/Moonshot/index.js +1 -1
- package/dist/esm/models/Yi/index.js +1 -1
- package/dist/esm/models/ZhiPu/index.js +1 -1
- package/dist/esm/models/image-model.d.ts +19 -0
- package/dist/esm/models/image-model.js +103 -0
- package/dist/esm/models/index.d.ts +2 -1
- package/dist/esm/models/index.js +3 -2
- package/dist/esm/models/model.js +1 -1
- package/dist/esm/type.d.ts +81 -0
- package/dist/esm/type.js +1 -1
- package/dist/esm/utils.d.ts +1 -1
- package/dist/esm/utils.js +9 -4
- package/dist/miniprogram/index.js +1 -1
- package/dist/miniprogram/index.js.LICENSE.txt +2 -2
- package/package.json +4 -4
- package/src/AI.ts +64 -17
- package/src/bot/index.ts +2 -0
- package/src/errors.ts +23 -0
- package/src/index.ts +27 -7
- package/src/models/Ark/index.ts +2 -0
- package/src/models/DashScope/index.ts +2 -0
- package/src/models/DeepSeek/index.ts +2 -0
- package/src/models/Default/index.ts +2 -0
- package/src/models/HunYuan/index.ts +2 -0
- package/src/models/HunYuan/util.ts +2 -0
- package/src/models/HunYuanBeta/index.ts +2 -0
- package/src/models/HunYuanExp/index.ts +2 -0
- package/src/models/HunYuanOpen/index.ts +2 -0
- package/src/models/Moonshot/index.ts +3 -0
- package/src/models/Yi/index.ts +2 -0
- package/src/models/ZhiPu/index.ts +2 -0
- package/src/models/image-model.ts +100 -0
- package/src/models/index.ts +2 -0
- package/src/models/model.ts +2 -0
- package/src/type.ts +216 -1
- package/src/utils.ts +21 -4
- package/tsconfig.json +1 -1
|
@@ -15,8 +15,8 @@ PERFORMANCE OF THIS SOFTWARE.
|
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* @license
|
|
18
|
-
* web-streams-polyfill v4.
|
|
19
|
-
* Copyright
|
|
18
|
+
* web-streams-polyfill v4.3.0
|
|
19
|
+
* Copyright 2026 Mattias Buelens, Diwank Singh Tomer and other contributors.
|
|
20
20
|
* This code is released under the MIT license.
|
|
21
21
|
* SPDX-License-Identifier: MIT
|
|
22
22
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloudbase/ai",
|
|
3
|
-
"version": "4.0.0",
|
|
3
|
+
"version": "4.0.1-alpha.0",
|
|
4
4
|
"description": "cloudbase js sdk ai module",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
"author": "",
|
|
31
31
|
"license": "Apache-2.0",
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@cloudbase/types": "4.0.0",
|
|
34
|
-
"@cloudbase/utilities": "4.0.0",
|
|
33
|
+
"@cloudbase/types": "4.0.1-alpha.0",
|
|
34
|
+
"@cloudbase/utilities": "4.0.1-alpha.0",
|
|
35
35
|
"@mattiasbuelens/web-streams-adapter": "^0.1.0",
|
|
36
36
|
"text-encoding-shim": "^1.0.5",
|
|
37
37
|
"web-streams-polyfill": "^4.0.0"
|
|
@@ -39,5 +39,5 @@
|
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@cloudbase/adapter-interface": "^0.7.1"
|
|
41
41
|
},
|
|
42
|
-
"gitHead": "
|
|
42
|
+
"gitHead": "f893174f5888080382b515a0a3ba1f4dd8999662"
|
|
43
43
|
}
|
package/src/AI.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
/* eslint-disable eqeqeq */
|
|
2
|
+
/* eslint-disable @typescript-eslint/naming-convention */
|
|
1
3
|
import type { SDKRequestInterface } from '@cloudbase/adapter-interface'
|
|
2
4
|
import { Bot } from './bot'
|
|
3
5
|
import * as models from './models'
|
|
@@ -9,15 +11,28 @@ import { langEvent } from '@cloudbase/utilities'
|
|
|
9
11
|
const { MODELS } = models
|
|
10
12
|
|
|
11
13
|
class AI {
|
|
12
|
-
public aiBaseUrl: string
|
|
13
|
-
public aiBotBaseUrl: string
|
|
14
14
|
public bot: Bot
|
|
15
15
|
public i18n: ICloudbaseConfig['i18n']
|
|
16
16
|
defaultHeaders: { [x: string]: any }
|
|
17
|
+
private _getBaseUrl?: () => string
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
this.
|
|
19
|
+
/** 动态获取 aiBaseUrl,支持 registerEndPointWithKey 后端点变更生效 */
|
|
20
|
+
get aiBaseUrl(): string {
|
|
21
|
+
return `${this._getBaseUrl ? this._getBaseUrl() : this.baseUrl}/ai`
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** 动态获取 aiBotBaseUrl,支持 registerEndPointWithKey 后端点变更生效 */
|
|
25
|
+
get aiBotBaseUrl(): string {
|
|
26
|
+
return `${this._getBaseUrl ? this._getBaseUrl() : this.baseUrl}/aibot`
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
constructor(
|
|
30
|
+
private req: SDKRequestInterface,
|
|
31
|
+
public baseUrl: string,
|
|
32
|
+
i18n: ICloudbaseConfig['i18n'],
|
|
33
|
+
getBaseUrl?: () => string,
|
|
34
|
+
) {
|
|
35
|
+
this._getBaseUrl = getBaseUrl
|
|
21
36
|
this.bot = new Bot(this.botRequest, this.aiBotBaseUrl)
|
|
22
37
|
this.i18n = i18n
|
|
23
38
|
|
|
@@ -29,25 +44,42 @@ class AI {
|
|
|
29
44
|
async handleResponseData(responseData: Promise<unknown> | ReadableStream<Uint8Array>, header?: Headers) {
|
|
30
45
|
const GO_TO_AI_TEXT = `${this.i18n.t('请检查调用方式,或前往云开发 AI+ 首页查看文档')}:https://tcb.cloud.tencent.com/dev#/ai`
|
|
31
46
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
throw new Error(`${this.i18n.t('AI+ 请求出错,错误码')}:${json.code},${this.i18n.t('错误信息')}:${
|
|
37
|
-
json.message
|
|
47
|
+
const throwIfError = (json: unknown) => {
|
|
48
|
+
if (typeof json === 'object' && json && 'code' in json && (json as any).code !== 'NORMAL') {
|
|
49
|
+
throw new Error(`${this.i18n.t('AI+ 请求出错,错误码')}:${(json as any).code},${this.i18n.t('错误信息')}:${
|
|
50
|
+
(json as any).message
|
|
38
51
|
}\n${GO_TO_AI_TEXT}\n${JSON.stringify(json, null, 2)}`,)
|
|
39
52
|
}
|
|
53
|
+
}
|
|
40
54
|
|
|
55
|
+
// 非流式请求:
|
|
56
|
+
// - 小程序/Web 适配器返回 Promise(has 'then')
|
|
57
|
+
// - Node 适配器已将 body 解析为普通对象(无 'then'、无 getReader)
|
|
58
|
+
// 两种情况都按 JSON 校验错误码后原样返回
|
|
59
|
+
if (typeof responseData === 'object' && responseData && typeof (responseData as any).getReader !== 'function') {
|
|
60
|
+
const json = 'then' in responseData ? await responseData : responseData
|
|
61
|
+
throwIfError(json)
|
|
41
62
|
return responseData
|
|
42
63
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
64
|
+
|
|
65
|
+
// 判断 responseData 是否是 ReadableStream 实例(兼容 Node.js 适配器非流式场景已解析为 JSON 对象的情况)
|
|
66
|
+
const isStream = typeof (responseData as any)?.getReader === 'function'
|
|
67
|
+
|
|
68
|
+
if (!isStream) {
|
|
69
|
+
// responseData 已经是解析后的 JSON 对象(如 Node.js 适配器非流式返回),直接检查错误码
|
|
70
|
+
const json = responseData as unknown as Record<string, unknown>
|
|
46
71
|
if (typeof json === 'object' && json && 'code' in json && json.code !== 'NORMAL') {
|
|
47
72
|
throw new Error(`${this.i18n.t('AI+ 请求出错,错误码')}:${json.code},${this.i18n.t('错误信息')}:${
|
|
48
73
|
json.message
|
|
49
74
|
}\n${GO_TO_AI_TEXT}\n${JSON.stringify(json, null, 2)}`,)
|
|
50
75
|
}
|
|
76
|
+
return responseData
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// 流式请求,如果接口出错,会变成传 json 格式的响应,通过 header 判断格式
|
|
80
|
+
if (header?.get?.('content-type')?.includes('application/json')) {
|
|
81
|
+
const json = await readableStream2JsonObject(responseData as ReadableStream<Uint8Array>)
|
|
82
|
+
throwIfError(json)
|
|
51
83
|
}
|
|
52
84
|
return responseData
|
|
53
85
|
}
|
|
@@ -81,6 +113,10 @@ class AI {
|
|
|
81
113
|
MODELS[name] = model
|
|
82
114
|
}
|
|
83
115
|
|
|
116
|
+
createImageModel<T extends 'hunyuan-image' | (string & {})>(provider: T) {
|
|
117
|
+
return new models.DefaultImageModel<T>(this.modelRequest, this.aiBaseUrl, provider)
|
|
118
|
+
}
|
|
119
|
+
|
|
84
120
|
modelRequest: types.ModelReq = async ({ url, data, headers, stream, timeout }) => {
|
|
85
121
|
const fetchHeaders = {
|
|
86
122
|
'Content-Type': 'application/json',
|
|
@@ -92,7 +128,7 @@ class AI {
|
|
|
92
128
|
method: 'post',
|
|
93
129
|
headers: { [this.i18n?.LANG_HEADER_KEY]: this.i18n?.lang, ...fetchHeaders, ...headers },
|
|
94
130
|
body: JSON.stringify(data),
|
|
95
|
-
url,
|
|
131
|
+
url: this.resolveUrl(url),
|
|
96
132
|
stream,
|
|
97
133
|
timeout,
|
|
98
134
|
})) as { data: Promise<unknown> | ReadableStream<Uint8Array>; header?: Headers }
|
|
@@ -101,8 +137,9 @@ class AI {
|
|
|
101
137
|
}
|
|
102
138
|
|
|
103
139
|
botRequest: types.BotReq = async ({ method, url, data = {}, headers, stream, timeout }) => {
|
|
140
|
+
const resolvedUrl = this.resolveUrl(url)
|
|
104
141
|
if (method === 'get') {
|
|
105
|
-
return this.handleResponseData((await this.req.fetch({ url: `${
|
|
142
|
+
return this.handleResponseData((await this.req.fetch({ url: `${resolvedUrl}?${objectToParam(data)}`, method, headers, stream, timeout })).data,)
|
|
106
143
|
}
|
|
107
144
|
|
|
108
145
|
const fetchHeaders = {
|
|
@@ -112,7 +149,7 @@ class AI {
|
|
|
112
149
|
stream && Object.assign(fetchHeaders, { Accept: 'text/event-stream' })
|
|
113
150
|
|
|
114
151
|
const { data: responseData, header } = (await this.req.fetch({
|
|
115
|
-
url,
|
|
152
|
+
url: resolvedUrl,
|
|
116
153
|
body: JSON.stringify(data),
|
|
117
154
|
headers: {
|
|
118
155
|
[this.i18n?.LANG_HEADER_KEY]: this.i18n?.lang,
|
|
@@ -139,6 +176,16 @@ class AI {
|
|
|
139
176
|
}
|
|
140
177
|
models.toolMap.set(functionTool.name, functionTool.fn)
|
|
141
178
|
}
|
|
179
|
+
|
|
180
|
+
/** 动态替换 URL 中的 origin 部分,支持 registerEndPointWithKey 后生效 */
|
|
181
|
+
private resolveUrl(url: string): string {
|
|
182
|
+
if (!this._getBaseUrl) return url
|
|
183
|
+
const currentBase = this._getBaseUrl()
|
|
184
|
+
if (currentBase !== this.baseUrl && url.startsWith(this.baseUrl)) {
|
|
185
|
+
return url.replace(this.baseUrl, currentBase)
|
|
186
|
+
}
|
|
187
|
+
return url
|
|
188
|
+
}
|
|
142
189
|
}
|
|
143
190
|
|
|
144
191
|
export { AI }
|
package/src/bot/index.ts
CHANGED
|
@@ -34,6 +34,7 @@ export class Bot {
|
|
|
34
34
|
req: BotReq
|
|
35
35
|
|
|
36
36
|
constructor(req: BotReq, public baseUrl: string) {
|
|
37
|
+
// eslint-disable-next-line prefer-rest-params
|
|
37
38
|
const token = arguments[2]
|
|
38
39
|
if (typeof token === 'string') {
|
|
39
40
|
this.req = ({ headers = {}, ...rest }) => req({ ...rest, headers: { ...headers, Authorization: `Bearer ${token}` } })
|
|
@@ -230,6 +231,7 @@ export class Bot {
|
|
|
230
231
|
type BotEventStreamData = { content: string }
|
|
231
232
|
|
|
232
233
|
class StreamResult {
|
|
234
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
233
235
|
private _eventSourceStream: ReadableStream<ParsedEvent>
|
|
234
236
|
|
|
235
237
|
constructor(_stream: ReadableStream<Uint8Array>) {
|
package/src/errors.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 参数校验错误类
|
|
3
|
+
* 用于统一参数校验错误的格式
|
|
4
|
+
*/
|
|
5
|
+
export class InvalidParamsError extends Error {
|
|
6
|
+
public code: string
|
|
7
|
+
public field?: string
|
|
8
|
+
|
|
9
|
+
constructor(message: string, field?: string) {
|
|
10
|
+
super(message)
|
|
11
|
+
this.name = 'InvalidParamsError'
|
|
12
|
+
this.code = 'INVALID_PARAMS'
|
|
13
|
+
this.field = field
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
toJSON() {
|
|
17
|
+
return {
|
|
18
|
+
code: this.code,
|
|
19
|
+
message: this.message,
|
|
20
|
+
field: this.field,
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable eqeqeq */
|
|
1
2
|
import type { IFetchOptions, SDKRequestInterface } from '@cloudbase/adapter-interface'
|
|
2
3
|
import type { ICloudbase, ICloudbaseConfig } from '@cloudbase/types'
|
|
3
4
|
import type { ICloudbaseComponent } from '@cloudbase/types/component'
|
|
@@ -54,9 +55,11 @@ interface AIInitOption {
|
|
|
54
55
|
baseUrl?: string
|
|
55
56
|
}
|
|
56
57
|
|
|
57
|
-
interface
|
|
58
|
+
interface ICreateAI {
|
|
58
59
|
req: SDKRequestInterface
|
|
59
60
|
baseUrl?: string
|
|
61
|
+
/** 动态获取 baseUrl 的函数,若提供则优先使用,支持端点变更后请求自动跟随 */
|
|
62
|
+
getBaseUrl?: () => string
|
|
60
63
|
env?: string
|
|
61
64
|
getAccessToken?: () => Promise<{ accessToken: string }>
|
|
62
65
|
handleReqInstance?: HandleRequestInstanceFunc
|
|
@@ -73,8 +76,11 @@ interface ICreateAi {
|
|
|
73
76
|
*
|
|
74
77
|
* 其他参数可按需传入覆盖函数逻辑。
|
|
75
78
|
*/
|
|
76
|
-
function
|
|
79
|
+
function createAI({ env, baseUrl, getBaseUrl: getBaseUrlFunc, req, getAccessToken, handleReqInstance, i18n }: ICreateAI) {
|
|
77
80
|
const getBaseUrl = () => {
|
|
81
|
+
if (getBaseUrlFunc != null) {
|
|
82
|
+
return getBaseUrlFunc()
|
|
83
|
+
}
|
|
78
84
|
if (baseUrl != null) {
|
|
79
85
|
return baseUrl
|
|
80
86
|
}
|
|
@@ -94,13 +100,19 @@ function createAi({ env, baseUrl, req, getAccessToken, handleReqInstance, i18n }
|
|
|
94
100
|
return handleReqInstance({ req })
|
|
95
101
|
}
|
|
96
102
|
|
|
97
|
-
return new AI(getReq(), getBaseUrl(), i18n)
|
|
103
|
+
return new AI(getReq(), getBaseUrl(), i18n, getBaseUrlFunc)
|
|
98
104
|
}
|
|
99
105
|
|
|
106
|
+
// 兼容
|
|
107
|
+
/**
|
|
108
|
+
* @deprecated use `createAI`
|
|
109
|
+
*/
|
|
110
|
+
const createAi = createAI
|
|
111
|
+
|
|
100
112
|
/**
|
|
101
113
|
* 创建 `AI` 实例。
|
|
102
114
|
* 该函数挂载在 js sdk 的 Cloudbase 实例上。
|
|
103
|
-
* 该函数调用了本模块暴露的 `
|
|
115
|
+
* 该函数调用了本模块暴露的 `createAI` 函数,但调用时通过传入参数做了逻辑覆盖:
|
|
104
116
|
*
|
|
105
117
|
* - 传入从 Cloudbase 实例上的中心的 `req`
|
|
106
118
|
* - 传入从 Cloudbase 实例上拿到的 `baseUrl`
|
|
@@ -123,9 +135,12 @@ function ai(
|
|
|
123
135
|
return `${PROTOCOL}${BASE_URL}`
|
|
124
136
|
}
|
|
125
137
|
|
|
126
|
-
|
|
138
|
+
// 若用户传了静态 baseUrl 则使用静态值,否则传入动态获取函数支持端点变更后生效
|
|
139
|
+
if (options?.baseUrl) {
|
|
140
|
+
return createAI({ req, baseUrl: options.baseUrl, handleReqInstance: ({ req }) => req, i18n: this.config.i18n })
|
|
141
|
+
}
|
|
127
142
|
|
|
128
|
-
return
|
|
143
|
+
return createAI({ req, baseUrl: getUrlFromCloud(), getBaseUrl: getUrlFromCloud, handleReqInstance: ({ req }) => req, i18n: this.config.i18n })
|
|
129
144
|
}
|
|
130
145
|
|
|
131
146
|
const component: ICloudbaseComponent = {
|
|
@@ -141,5 +156,10 @@ function registerAi(app: ICloudbase) {
|
|
|
141
156
|
}
|
|
142
157
|
}
|
|
143
158
|
|
|
144
|
-
export { AI, Bot, createAi, restModels as models, registerAi, utils }
|
|
159
|
+
export { AI, Bot, createAi, createAI, restModels as models, registerAi, utils }
|
|
145
160
|
export * from './type'
|
|
161
|
+
export * from './errors'
|
|
162
|
+
|
|
163
|
+
try {
|
|
164
|
+
(window as any).registerAi = registerAi
|
|
165
|
+
} catch (e) {}
|
package/src/models/Ark/index.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable eqeqeq */
|
|
1
2
|
import {
|
|
2
3
|
createAsyncIterable,
|
|
3
4
|
TransformStream,
|
|
@@ -42,6 +43,7 @@ export class DeepSeekSimpleModel implements SimpleChatModel {
|
|
|
42
43
|
|
|
43
44
|
public async doStream(data: BaseChatModelInput, options?: ReqOptions): Promise<DoStreamOutput> {
|
|
44
45
|
let isToolCall: null | boolean = null
|
|
46
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
45
47
|
const _stream = await this.req({
|
|
46
48
|
url: this.url,
|
|
47
49
|
data: {
|
|
@@ -33,6 +33,7 @@ export class DefaultSimpleModel implements SimpleChatModel {
|
|
|
33
33
|
public async doStream(data: BaseChatModelInput): Promise<DoStreamOutput> {
|
|
34
34
|
let isToolCall: null | boolean = null
|
|
35
35
|
|
|
36
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
36
37
|
const _stream = await this.req({
|
|
37
38
|
url: this.url,
|
|
38
39
|
data: {
|
|
@@ -48,6 +49,7 @@ export class DefaultSimpleModel implements SimpleChatModel {
|
|
|
48
49
|
transform(chunk, controller) {
|
|
49
50
|
const newChoices = chunk.choices.map((choice) => {
|
|
50
51
|
const message = choice.delta
|
|
52
|
+
// eslint-disable-next-line eqeqeq
|
|
51
53
|
if (isToolCall == null) isToolCall = isToolCallAssistantMessage(message)
|
|
52
54
|
if (isToolCall) {
|
|
53
55
|
return {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable eqeqeq */
|
|
1
2
|
import {
|
|
2
3
|
createAsyncIterable,
|
|
3
4
|
TransformStream,
|
|
@@ -52,6 +53,7 @@ export class HunYuanSimpleModel implements SimpleChatModel {
|
|
|
52
53
|
public async doStream(data: BaseChatModelInput, options?: ReqOptions): Promise<DoStreamOutput> {
|
|
53
54
|
let isToolCall: null | boolean = null
|
|
54
55
|
|
|
56
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
55
57
|
const _stream = await this.req({
|
|
56
58
|
url: this.url,
|
|
57
59
|
headers: {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable eqeqeq */
|
|
1
2
|
import {
|
|
2
3
|
createAsyncIterable,
|
|
3
4
|
TransformStream,
|
|
@@ -45,6 +46,7 @@ export class HunYuanOpenSimpleModel implements SimpleChatModel {
|
|
|
45
46
|
public async doStream(data: BaseChatModelInput, options?: ReqOptions): Promise<DoStreamOutput> {
|
|
46
47
|
let isToolCall: null | boolean = null
|
|
47
48
|
|
|
49
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
48
50
|
const _stream = await this.req({
|
|
49
51
|
url: this.url,
|
|
50
52
|
data: {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable eqeqeq */
|
|
1
2
|
import {
|
|
2
3
|
createAsyncIterable,
|
|
3
4
|
TransformStream,
|
|
@@ -17,6 +18,7 @@ import type {
|
|
|
17
18
|
} from '../../type'
|
|
18
19
|
|
|
19
20
|
function processInput(input: BaseChatModelInput): MoonshotInputData {
|
|
21
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
20
22
|
const { messages, model, temperature, tools, top_p } = input
|
|
21
23
|
|
|
22
24
|
return {
|
|
@@ -56,6 +58,7 @@ export class MoonshotSimpleModel implements SimpleChatModel {
|
|
|
56
58
|
|
|
57
59
|
public async doStream(data: BaseChatModelInput, options?: ReqOptions): Promise<DoStreamOutput> {
|
|
58
60
|
let isToolCall: null | boolean = null
|
|
61
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
59
62
|
const _stream = await this.req({
|
|
60
63
|
url: this.url,
|
|
61
64
|
data: {
|
package/src/models/Yi/index.ts
CHANGED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ModelReq,
|
|
3
|
+
// ImageEditInput,
|
|
4
|
+
HunyuanGenerateImageInput,
|
|
5
|
+
HunyuanGenerateImageOutput,
|
|
6
|
+
HunyuanARGenerateImageInput,
|
|
7
|
+
HunyuanARGenerateImageOutput,
|
|
8
|
+
// HunyuanEditImageInput,
|
|
9
|
+
// HunyuanEditImageOutput,
|
|
10
|
+
} from '../type'
|
|
11
|
+
import { InvalidParamsError } from '../errors'
|
|
12
|
+
|
|
13
|
+
interface HunyuanImageGenerateFn {
|
|
14
|
+
(input: HunyuanARGenerateImageInput): Promise<HunyuanARGenerateImageOutput>
|
|
15
|
+
(input: HunyuanGenerateImageInput): Promise<HunyuanGenerateImageOutput>
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
type GenerateImageFn<TProvider> = TProvider extends 'hunyuan-image'
|
|
19
|
+
? HunyuanImageGenerateFn
|
|
20
|
+
: (input: unknown) => Promise<unknown>
|
|
21
|
+
|
|
22
|
+
export class DefaultImageModel<TProvider extends string> {
|
|
23
|
+
public defaultGenerateImageSubUrl = 'images/ar/generations'
|
|
24
|
+
|
|
25
|
+
public generateImageSubUrlConfig: Record<string, Array<[RegExp, string]>> = {
|
|
26
|
+
'hunyuan-image': [
|
|
27
|
+
[/^hunyuan-image(-v[12](\..*)?)?$/, 'images/generations'],
|
|
28
|
+
],
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** 生成图片 */
|
|
32
|
+
public generateImage: GenerateImageFn<TProvider>
|
|
33
|
+
|
|
34
|
+
constructor(
|
|
35
|
+
private req: ModelReq,
|
|
36
|
+
public baseUrl: string,
|
|
37
|
+
public provider: TProvider,
|
|
38
|
+
) {
|
|
39
|
+
this.generateImage = this.generateImageImpl.bind(this) as GenerateImageFn<TProvider>
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** generateImage 的实际实现 */
|
|
43
|
+
private async generateImageImpl(input: HunyuanARGenerateImageInput | HunyuanGenerateImageInput,): Promise<HunyuanARGenerateImageOutput | HunyuanGenerateImageOutput> {
|
|
44
|
+
// 当模型为 HY-Image-v3.0-I2I-ToB-v1.0.1 且 provider 为空或为 hunyuan-image 时校验参数
|
|
45
|
+
if (
|
|
46
|
+
typeof input === 'object' && input && 'model' in input && input.model === 'HY-Image-v3.0-I2I-ToB-v1.0.1' && (this.provider === '' || this.provider === 'hunyuan-image')
|
|
47
|
+
) {
|
|
48
|
+
const typedInput = input
|
|
49
|
+
const imageUrls = typedInput.image_urls as string[] | undefined
|
|
50
|
+
const images = typedInput.images as string[] | undefined
|
|
51
|
+
|
|
52
|
+
if (imageUrls && imageUrls.length > 1) {
|
|
53
|
+
throw new InvalidParamsError(
|
|
54
|
+
'当模型为 HY-Image-v3.0-I2I-ToB-v1.0.1 时,image_urls 最多只能有 1 个元素',
|
|
55
|
+
'image_urls',
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
if (images && images.length > 1) {
|
|
59
|
+
throw new InvalidParamsError(
|
|
60
|
+
'当模型为 HY-Image-v3.0-I2I-ToB-v1.0.1 时,images 最多只能有 1 个元素',
|
|
61
|
+
'images',
|
|
62
|
+
)
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
let subUrl = this.defaultGenerateImageSubUrl
|
|
67
|
+
|
|
68
|
+
if (typeof input === 'object' && input && 'model' in input && typeof input.model === 'string') {
|
|
69
|
+
const newSubUrl = this.getGenerateImageSubUrl(this.provider, input.model)
|
|
70
|
+
if (newSubUrl) subUrl = newSubUrl
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const res = (await this.req({
|
|
74
|
+
url: this.getGenerateUrl(subUrl),
|
|
75
|
+
data: input,
|
|
76
|
+
stream: false,
|
|
77
|
+
})) as HunyuanARGenerateImageOutput | HunyuanGenerateImageOutput
|
|
78
|
+
|
|
79
|
+
return res
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
private getGenerateUrl(subUrl: string) {
|
|
83
|
+
return `${this.baseUrl}/${this.provider}/${subUrl}`
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* 根据 provider 与 model 解析生成图片的子路径。
|
|
88
|
+
* 按配置顺序用 RegExp 匹配,命中即返回对应 subUrl。
|
|
89
|
+
*/
|
|
90
|
+
private getGenerateImageSubUrl(provider: string, model: string): string | undefined {
|
|
91
|
+
const rules = this.generateImageSubUrlConfig[provider]
|
|
92
|
+
if (!rules) return undefined
|
|
93
|
+
|
|
94
|
+
for (const [pattern, subUrl] of rules) {
|
|
95
|
+
if (pattern.test(model)) return subUrl
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return undefined
|
|
99
|
+
}
|
|
100
|
+
}
|
package/src/models/index.ts
CHANGED
|
@@ -9,6 +9,7 @@ import { HunYuanExpSimpleModel } from './HunYuanExp/index'
|
|
|
9
9
|
import { HunYuanOpenSimpleModel } from './HunYuanOpen/index'
|
|
10
10
|
import { DeepSeekSimpleModel } from './DeepSeek'
|
|
11
11
|
import { DefaultSimpleModel } from './Default'
|
|
12
|
+
import { DefaultImageModel } from './image-model'
|
|
12
13
|
|
|
13
14
|
export const MODELS = {
|
|
14
15
|
hunyuan: HunYuanSimpleModel,
|
|
@@ -34,6 +35,7 @@ export {
|
|
|
34
35
|
HunYuanExpSimpleModel,
|
|
35
36
|
HunYuanOpenSimpleModel,
|
|
36
37
|
DefaultSimpleModel,
|
|
38
|
+
DefaultImageModel,
|
|
37
39
|
}
|
|
38
40
|
|
|
39
41
|
export { ReactModel, toolMap } from './model'
|