@vectorx/ai-sdk 0.4.0 → 0.5.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/lib/ai.js CHANGED
@@ -57,6 +57,8 @@ class AI {
57
57
  switch (model) {
58
58
  case models.MultiModalModelName.QwenImage:
59
59
  return new models.ReActModel(new models.QwenImageModel(this.request, models.QwenImageModel.BASE_URL, this.tokenManager));
60
+ case models.MultiModalModelName.QwenImageEdit:
61
+ return new models.ReActModel(new models.QwenImageEditModel(this.request, models.QwenImageEditModel.BASE_URL, this.tokenManager));
60
62
  case models.MultiModalModelName.WanxSketchToImageLite:
61
63
  return new models.ReActModel(new models.WanxSketchToImageLiteModel(this.request, models.WanxSketchToImageLiteModel.BASE_URL, this.tokenManager));
62
64
  case models.MultiModalModelName.QwenStyleRepaintV1:
@@ -27,13 +27,6 @@ class QwenDocTurbo extends Chat_1.SimpleChatModel {
27
27
  if (isStreaming) {
28
28
  fetchHeaders["X-DashScope-SSE"] = "enable";
29
29
  }
30
- console.log("=== QwenDocTurbo Request ===", {
31
- method: "post",
32
- headers: Object.assign({}, fetchHeaders),
33
- body: JSON.stringify(data),
34
- url: `${this.baseUrl}/${this.subUrl}`,
35
- stream: isStreaming,
36
- });
37
30
  const { data: responseData, header } = (yield this.req.fetch({
38
31
  method: "post",
39
32
  headers: Object.assign({}, fetchHeaders),
@@ -0,0 +1,77 @@
1
+ import type { IAbstractRequest } from "@vectorx/ai-types";
2
+ import type { DoGenerateOutput, DoStreamOutput, ModelRequestOptions, ReqOptions } from "../../model-type";
3
+ import { TokenManager } from "../../tokenManager";
4
+ import { SimpleChatModel } from "../Chat";
5
+ export interface QwenImageEditParameters {
6
+ negative_prompt?: string;
7
+ watermark?: boolean;
8
+ }
9
+ export interface QwenImageEditAPIInput {
10
+ model: string;
11
+ input: {
12
+ messages: Array<{
13
+ role: "user";
14
+ content: Array<{
15
+ image?: string;
16
+ text?: string;
17
+ }>;
18
+ }>;
19
+ };
20
+ parameters?: QwenImageEditParameters;
21
+ }
22
+ export type QwenImageEditRequestOptions = QwenImageEditAPIInput & {
23
+ parameters?: QwenImageEditParameters;
24
+ };
25
+ export type QwenImageEditContentItem = {
26
+ image?: string;
27
+ url?: string;
28
+ image_url?: string | {
29
+ url: string;
30
+ };
31
+ b64_json?: string;
32
+ [key: string]: any;
33
+ };
34
+ export interface QwenImageEditAPIResponse {
35
+ async?: boolean;
36
+ output: {
37
+ choices?: Array<{
38
+ finish_reason: string;
39
+ message: {
40
+ role: "assistant" | "user";
41
+ content: QwenImageEditContentItem[];
42
+ };
43
+ }>;
44
+ task_status?: string;
45
+ task_id?: string;
46
+ task_metric?: {
47
+ TOTAL: number;
48
+ FAILED: number;
49
+ SUCCEEDED: number;
50
+ };
51
+ };
52
+ usage?: {
53
+ width?: number;
54
+ height?: number;
55
+ image_count?: number;
56
+ };
57
+ request_id?: string;
58
+ id?: string;
59
+ model?: string;
60
+ created?: number;
61
+ object?: string;
62
+ code?: number;
63
+ error?: string;
64
+ }
65
+ export declare class QwenImageEditModel extends SimpleChatModel {
66
+ static BASE_URL: string;
67
+ static SUB_GENERATION_URL: string;
68
+ modelName: string;
69
+ constructor(req: IAbstractRequest, baseUrl: string, tokenManager: TokenManager);
70
+ protected normalizeStandardImageEditCompletion(res: QwenImageEditAPIResponse, fallbackModel: string): DoGenerateOutput;
71
+ protected coverModelRequestToQwenInput(data: ModelRequestOptions & {
72
+ parameters?: QwenImageEditParameters;
73
+ }): QwenImageEditRequestOptions;
74
+ protected modelRequest(data: QwenImageEditRequestOptions, options?: ReqOptions): Promise<ReadableStream<Uint8Array> | Promise<unknown>>;
75
+ doGenerate(data: ModelRequestOptions, options?: ReqOptions): Promise<DoGenerateOutput>;
76
+ doStream(data: ModelRequestOptions, options?: ReqOptions): Promise<DoStreamOutput>;
77
+ }
@@ -0,0 +1,205 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.QwenImageEditModel = void 0;
13
+ const stream_1 = require("../../stream");
14
+ const utils_1 = require("../../utils");
15
+ const Chat_1 = require("../Chat");
16
+ class QwenImageEditModel extends Chat_1.SimpleChatModel {
17
+ constructor(req, baseUrl, tokenManager) {
18
+ super(req, baseUrl, QwenImageEditModel.SUB_GENERATION_URL, tokenManager);
19
+ this.modelName = "qwen-image-edit";
20
+ }
21
+ normalizeStandardImageEditCompletion(res, fallbackModel) {
22
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
23
+ const qOutput = (res === null || res === void 0 ? void 0 : res.output) || {};
24
+ if ((qOutput === null || qOutput === void 0 ? void 0 : qOutput.task_status) && (qOutput === null || qOutput === void 0 ? void 0 : qOutput.task_id)) {
25
+ const created = (_a = res === null || res === void 0 ? void 0 : res.created) !== null && _a !== void 0 ? _a : Math.floor(Date.now() / 1000);
26
+ const id = (res === null || res === void 0 ? void 0 : res.id) || (res === null || res === void 0 ? void 0 : res.request_id) || "";
27
+ const normalized = {
28
+ id,
29
+ object: (_b = res === null || res === void 0 ? void 0 : res.object) !== null && _b !== void 0 ? _b : "chat.completion",
30
+ created,
31
+ model: (_c = res === null || res === void 0 ? void 0 : res.model) !== null && _c !== void 0 ? _c : fallbackModel,
32
+ log_id: id,
33
+ error: (_d = res === null || res === void 0 ? void 0 : res.error) !== null && _d !== void 0 ? _d : "",
34
+ code: (_e = res === null || res === void 0 ? void 0 : res.code) !== null && _e !== void 0 ? _e : 0,
35
+ choices: [
36
+ {
37
+ index: 0,
38
+ message: {
39
+ id,
40
+ role: "assistant",
41
+ type: "async_task",
42
+ content: JSON.stringify(Object.assign(Object.assign({}, ((res === null || res === void 0 ? void 0 : res.output) || {})), { request_id: (res === null || res === void 0 ? void 0 : res.request_id) || id })),
43
+ reasoning_content: "",
44
+ },
45
+ finish_reason: "stop",
46
+ },
47
+ ],
48
+ usage: mapUsageToStandard(res === null || res === void 0 ? void 0 : res.usage),
49
+ };
50
+ return normalized;
51
+ }
52
+ const first = ((_g = (_f = qOutput === null || qOutput === void 0 ? void 0 : qOutput.choices) === null || _f === void 0 ? void 0 : _f[0]) !== null && _g !== void 0 ? _g : null);
53
+ const message = (_h = first === null || first === void 0 ? void 0 : first.message) !== null && _h !== void 0 ? _h : {};
54
+ const contentUrl = Array.isArray(message === null || message === void 0 ? void 0 : message.content) && ((_j = message.content[0]) === null || _j === void 0 ? void 0 : _j.image) ? String(message.content[0].image) : "";
55
+ const created = (_k = res === null || res === void 0 ? void 0 : res.created) !== null && _k !== void 0 ? _k : Math.floor(Date.now() / 1000);
56
+ const id = (res === null || res === void 0 ? void 0 : res.id) || (res === null || res === void 0 ? void 0 : res.request_id) || "";
57
+ const normalized = {
58
+ id,
59
+ object: (_l = res === null || res === void 0 ? void 0 : res.object) !== null && _l !== void 0 ? _l : "chat.completion",
60
+ created,
61
+ model: (_m = res === null || res === void 0 ? void 0 : res.model) !== null && _m !== void 0 ? _m : fallbackModel,
62
+ log_id: id,
63
+ error: (_o = res === null || res === void 0 ? void 0 : res.error) !== null && _o !== void 0 ? _o : "",
64
+ code: (_p = res === null || res === void 0 ? void 0 : res.code) !== null && _p !== void 0 ? _p : 0,
65
+ choices: [
66
+ {
67
+ index: 0,
68
+ message: {
69
+ id,
70
+ role: "assistant",
71
+ type: "image",
72
+ content: contentUrl || "",
73
+ reasoning_content: "",
74
+ },
75
+ finish_reason: (_q = first === null || first === void 0 ? void 0 : first.finish_reason) !== null && _q !== void 0 ? _q : "stop",
76
+ },
77
+ ],
78
+ usage: mapUsageToStandard(res === null || res === void 0 ? void 0 : res.usage),
79
+ };
80
+ return normalized;
81
+ }
82
+ coverModelRequestToQwenInput(data) {
83
+ var _a, _b;
84
+ const imageUrls = [];
85
+ const texts = [];
86
+ const messages = data.messages || data.history || [];
87
+ if (Array.isArray(messages) && messages.length > 0) {
88
+ const firstUser = (_a = messages.find((m) => (m === null || m === void 0 ? void 0 : m.role) === "user")) !== null && _a !== void 0 ? _a : messages[0];
89
+ const c = firstUser === null || firstUser === void 0 ? void 0 : firstUser.content;
90
+ if (Array.isArray(c)) {
91
+ for (const p of c) {
92
+ if ((p === null || p === void 0 ? void 0 : p.type) === "image_url" && ((_b = p.image_url) === null || _b === void 0 ? void 0 : _b.url)) {
93
+ imageUrls.push(p.image_url.url);
94
+ }
95
+ else if ((p === null || p === void 0 ? void 0 : p.type) === "text" && typeof p.text === "string" && p.text.trim()) {
96
+ texts.push(p.text.trim());
97
+ }
98
+ }
99
+ }
100
+ }
101
+ if (imageUrls.length === 0 && data.image) {
102
+ imageUrls.push(String(data.image));
103
+ }
104
+ if (texts.length === 0 && data.msg) {
105
+ texts.push(String(data.msg));
106
+ }
107
+ if (texts.length === 0 && data.prompt) {
108
+ texts.push(String(data.prompt));
109
+ }
110
+ if (imageUrls.length === 0)
111
+ throw new Error("QwenImageEdit 需要提供至少一个图片 URL");
112
+ if (texts.length === 0)
113
+ throw new Error("QwenImageEdit 需要提供至少一个文本提示词");
114
+ const content = [];
115
+ imageUrls.forEach((url) => {
116
+ content.push({ image: url });
117
+ });
118
+ texts.forEach((text) => {
119
+ content.push({ text });
120
+ });
121
+ return {
122
+ parameters: data.parameters,
123
+ model: this.modelName,
124
+ input: {
125
+ messages: [
126
+ {
127
+ role: "user",
128
+ content,
129
+ },
130
+ ],
131
+ },
132
+ };
133
+ }
134
+ modelRequest(data_1) {
135
+ return __awaiter(this, arguments, void 0, function* (data, options = { timeout: 30 * 1000 }) {
136
+ const fetchHeaders = yield this.createAuthHeaders(options === null || options === void 0 ? void 0 : options.headers);
137
+ const joinedUrl = `${String(this.baseUrl).replace(/\/+$/, "")}/${String(this.subUrl).replace(/^\/+/, "")}`;
138
+ const { data: responseData, header } = (yield this.req.fetch({
139
+ url: joinedUrl,
140
+ headers: Object.assign({}, fetchHeaders),
141
+ body: JSON.stringify(data),
142
+ method: "post",
143
+ stream: false,
144
+ }));
145
+ return (0, utils_1.handleResponseData)(responseData, header);
146
+ });
147
+ }
148
+ doGenerate(data, options) {
149
+ return __awaiter(this, void 0, void 0, function* () {
150
+ data.model = this.modelName;
151
+ const payload = this.coverModelRequestToQwenInput(data);
152
+ const res = (yield this.modelRequest(payload, options));
153
+ return this.normalizeStandardImageEditCompletion(res, this.modelName);
154
+ });
155
+ }
156
+ doStream(data, options) {
157
+ return __awaiter(this, void 0, void 0, function* () {
158
+ var _a, _b;
159
+ const nonStream = yield this.doGenerate(Object.assign({}, data), options);
160
+ const msg = ((_b = (_a = nonStream.choices) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.message) || {};
161
+ const singleChunk = {
162
+ id: nonStream.id,
163
+ object: "chat.completion.chunk",
164
+ created: nonStream.created,
165
+ model: nonStream.model,
166
+ log_id: nonStream.log_id,
167
+ error: nonStream.error || "",
168
+ code: nonStream.code || 0,
169
+ choices: [
170
+ {
171
+ index: 0,
172
+ message: {
173
+ id: nonStream.id,
174
+ role: "assistant",
175
+ type: msg.type || "image",
176
+ content: msg.content || "",
177
+ reasoning_content: "",
178
+ },
179
+ finish_reason: "stop",
180
+ },
181
+ ],
182
+ usage: nonStream.usage,
183
+ };
184
+ const stream = new stream_1.ReadableStream({
185
+ start(controller) {
186
+ controller.enqueue(singleChunk);
187
+ controller.close();
188
+ },
189
+ });
190
+ return (0, stream_1.createAsyncIterable)(stream);
191
+ });
192
+ }
193
+ }
194
+ exports.QwenImageEditModel = QwenImageEditModel;
195
+ QwenImageEditModel.BASE_URL = "https://dashscope.aliyuncs.com";
196
+ QwenImageEditModel.SUB_GENERATION_URL = "api/v1/services/aigc/multimodal-generation/generation";
197
+ function mapUsageToStandard(usage) {
198
+ return {
199
+ prompt_tokens: 0,
200
+ completion_tokens: 0,
201
+ knowledge_tokens: 0,
202
+ reasoning_tokens: 0,
203
+ total_tokens: 0,
204
+ };
205
+ }
@@ -1,6 +1,7 @@
1
1
  import { DefaultSimpleModel } from "./Default";
2
2
  import { QwenDocTurbo } from "./QwenDocTurbo";
3
3
  import { QwenImageModel } from "./QwenImage";
4
+ import { QwenImageEditModel } from "./QwenImageEdit";
4
5
  import { WanxSketchToImageLiteModel } from "./QwenSketchToImage";
5
6
  import { QwenStyleRepaintV1Model } from "./QwenStyleRepaintV1";
6
7
  import { QwenVlMax } from "./QwenVlMax";
@@ -23,6 +24,7 @@ export declare enum MultiModalModelName {
23
24
  Wanx21T2iPlus = "wanx2.1-t2i-plus",
24
25
  Wanx21T2iTurbo = "wanx2.1-t2i-turbo",
25
26
  QwenImage = "qwen-image",
27
+ QwenImageEdit = "qwen-image-edit",
26
28
  WanxSketchToImageLite = "wanx-sketch-to-image-lite",
27
29
  QwenStyleRepaintV1 = "wanx-style-repaint-v1"
28
30
  }
@@ -41,10 +43,11 @@ export declare const modelName: {
41
43
  "wanx2.1-t2i-plus": string;
42
44
  "wanx2.1-t2i-turbo": string;
43
45
  "qwen-image": string;
46
+ "qwen-image-edit": string;
44
47
  "wanx-sketch-to-image-lite": string;
45
48
  "wanx-style-repaint-v1": string;
46
49
  };
47
50
  export declare const isValidModel: (model: ModelName | MultiModalModelName) => model is ModelName | MultiModalModelName;
48
51
  export declare const isMultiModalModel: (model: ModelName | MultiModalModelName) => model is MultiModalModelName;
49
52
  declare const toolMap: Map<string, Function>;
50
- export { DefaultSimpleModel, QwenDocTurbo, ReActModel, toolMap, WanxSketchToImageLiteModel, QwenImageModel, QwenVlMax, QwenStyleRepaintV1Model, };
53
+ export { DefaultSimpleModel, QwenDocTurbo, ReActModel, toolMap, WanxSketchToImageLiteModel, QwenImageModel, QwenImageEditModel, QwenVlMax, QwenStyleRepaintV1Model, };
@@ -1,12 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.QwenStyleRepaintV1Model = exports.QwenVlMax = exports.QwenImageModel = exports.WanxSketchToImageLiteModel = exports.toolMap = exports.ReActModel = exports.QwenDocTurbo = exports.DefaultSimpleModel = exports.isMultiModalModel = exports.isValidModel = exports.modelName = exports.MultiModalModelName = exports.ModelName = void 0;
3
+ exports.QwenStyleRepaintV1Model = exports.QwenVlMax = exports.QwenImageEditModel = exports.QwenImageModel = exports.WanxSketchToImageLiteModel = exports.toolMap = exports.ReActModel = exports.QwenDocTurbo = exports.DefaultSimpleModel = exports.isMultiModalModel = exports.isValidModel = exports.modelName = exports.MultiModalModelName = exports.ModelName = void 0;
4
4
  const Default_1 = require("./Default");
5
5
  Object.defineProperty(exports, "DefaultSimpleModel", { enumerable: true, get: function () { return Default_1.DefaultSimpleModel; } });
6
6
  const QwenDocTurbo_1 = require("./QwenDocTurbo");
7
7
  Object.defineProperty(exports, "QwenDocTurbo", { enumerable: true, get: function () { return QwenDocTurbo_1.QwenDocTurbo; } });
8
8
  const QwenImage_1 = require("./QwenImage");
9
9
  Object.defineProperty(exports, "QwenImageModel", { enumerable: true, get: function () { return QwenImage_1.QwenImageModel; } });
10
+ const QwenImageEdit_1 = require("./QwenImageEdit");
11
+ Object.defineProperty(exports, "QwenImageEditModel", { enumerable: true, get: function () { return QwenImageEdit_1.QwenImageEditModel; } });
10
12
  const QwenSketchToImage_1 = require("./QwenSketchToImage");
11
13
  Object.defineProperty(exports, "WanxSketchToImageLiteModel", { enumerable: true, get: function () { return QwenSketchToImage_1.WanxSketchToImageLiteModel; } });
12
14
  const QwenStyleRepaintV1_1 = require("./QwenStyleRepaintV1");
@@ -35,6 +37,7 @@ var MultiModalModelName;
35
37
  MultiModalModelName["Wanx21T2iPlus"] = "wanx2.1-t2i-plus";
36
38
  MultiModalModelName["Wanx21T2iTurbo"] = "wanx2.1-t2i-turbo";
37
39
  MultiModalModelName["QwenImage"] = "qwen-image";
40
+ MultiModalModelName["QwenImageEdit"] = "qwen-image-edit";
38
41
  MultiModalModelName["WanxSketchToImageLite"] = "wanx-sketch-to-image-lite";
39
42
  MultiModalModelName["QwenStyleRepaintV1"] = "wanx-style-repaint-v1";
40
43
  })(MultiModalModelName || (exports.MultiModalModelName = MultiModalModelName = {}));
@@ -53,6 +56,7 @@ exports.modelName = {
53
56
  [MultiModalModelName.Wanx21T2iPlus]: "wanx2.1-t2i-plus",
54
57
  [MultiModalModelName.Wanx21T2iTurbo]: "wanx2.1-t2i-turbo",
55
58
  [MultiModalModelName.QwenImage]: "qwen-image",
59
+ [MultiModalModelName.QwenImageEdit]: "qwen-image-edit",
56
60
  [MultiModalModelName.WanxSketchToImageLite]: "wanx-sketch-to-image-lite",
57
61
  [MultiModalModelName.QwenStyleRepaintV1]: "wanx-style-repaint-v1",
58
62
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vectorx/ai-sdk",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Cloud AI SDK",
5
5
  "main": "lib/index.js",
6
6
  "sideEffects": false,