doomiaichat 7.1.7 → 7.1.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/dist/corzbot.d.ts CHANGED
@@ -4,10 +4,12 @@
4
4
  import { CozeAPI, EnterMessage } from '@coze/api';
5
5
  import GptBase from "./gptbase";
6
6
  import { CorzAuthorization } from './corzauthorization';
7
+ import { ApiResult } from './declare';
7
8
  export default class CorzBot extends GptBase {
8
9
  private authorizationProvider;
9
10
  private setting;
10
11
  protected botid: string;
12
+ protected workflowid: string;
11
13
  private apiKey;
12
14
  private lastThinkingMessage;
13
15
  /**
@@ -21,20 +23,32 @@ export default class CorzBot extends GptBase {
21
23
  * 发起一次会话
22
24
  */
23
25
  createCoversation(client?: CozeAPI): Promise<string | null>;
26
+ setVariables(params: any): Promise<ApiResult>;
24
27
  /**
25
- * 组装请求参数
26
- * @param message
27
- * @param callChatOption
28
- * @param attach
29
- * @param _axiosOption
30
- */
28
+ * 获取设置的变量
29
+ * @returns
30
+ */
31
+ getVariables(params: any): Promise<any>;
32
+ /**
33
+ * 组装请求参数
34
+ * @param message
35
+ * @param callChatOption
36
+ * @param attach
37
+ * @param _axiosOption
38
+ */
31
39
  getRequestStream<T>(client: CozeAPI, message: EnterMessage[], callChatOption?: any): Promise<T>;
32
40
  /**
33
- * 非流式传输聊天请求
34
- * @param chatText
35
- * @param callChatOption
36
- * @param _axiosOption
37
- */
41
+ * 同步调用的问答请求需要获取会话详情
42
+ * @param chatid
43
+ * @param conversation_id
44
+ */
45
+ private getChatDetail;
46
+ /**
47
+ * 非流式传输聊天请求
48
+ * @param chatText
49
+ * @param callChatOption
50
+ * @param _axiosOption
51
+ */
38
52
  chatRequest(message: any[] | string, callChatOption?: any, _axiosOption?: any): Promise<any>;
39
53
  /**
40
54
  * 解析深度思考的JSON内容
package/dist/corzbot.js CHANGED
@@ -37,9 +37,8 @@ var DeepThinkingStatus;
37
37
  (function (DeepThinkingStatus) {
38
38
  DeepThinkingStatus[DeepThinkingStatus["None"] = 0] = "None";
39
39
  DeepThinkingStatus[DeepThinkingStatus["Thinking"] = 1] = "Thinking";
40
- DeepThinkingStatus[DeepThinkingStatus["ReasonOutput"] = 2] = "ReasonOutput";
41
- DeepThinkingStatus[DeepThinkingStatus["CardResource"] = 3] = "CardResource";
42
- DeepThinkingStatus[DeepThinkingStatus["ThinkingOver"] = 4] = "ThinkingOver";
40
+ DeepThinkingStatus[DeepThinkingStatus["ContentOutput"] = 2] = "ContentOutput";
41
+ DeepThinkingStatus[DeepThinkingStatus["ThinkingOver"] = 3] = "ThinkingOver";
43
42
  })(DeepThinkingStatus || (DeepThinkingStatus = {}));
44
43
  class CorzBot extends gptbase_1.default {
45
44
  // protected client: CozeAPI;
@@ -55,6 +54,7 @@ class CorzBot extends gptbase_1.default {
55
54
  this.lastThinkingMessage = { action: '', textposition: 0 };
56
55
  ////初始化扣子客户端
57
56
  this.botid = this.setting['botid'] || this.setting['botID'];
57
+ this.workflowid = this.setting['workflowid'];
58
58
  this.apiKey = this.setting['apiKey'];
59
59
  }
60
60
  createClient() {
@@ -75,7 +75,8 @@ class CorzBot extends gptbase_1.default {
75
75
  return __awaiter(this, void 0, void 0, function* () {
76
76
  try {
77
77
  const czApi = client !== null && client !== void 0 ? client : yield this.createClient();
78
- const result = yield czApi.conversations.create({ bot_id: this.botid });
78
+ const params = this.botid ? { bot_id: this.botid } : {};
79
+ const result = yield czApi.conversations.create(params);
79
80
  return result.id;
80
81
  }
81
82
  catch (error) {
@@ -84,19 +85,41 @@ class CorzBot extends gptbase_1.default {
84
85
  }
85
86
  });
86
87
  }
88
+ setVariables(params) {
89
+ return __awaiter(this, void 0, void 0, function* () {
90
+ const client = yield this.createClient();
91
+ const cozeParams = Object.assign({}, this.botid ? { bot_id: this.botid } : {}, params);
92
+ client.variables.update(cozeParams);
93
+ return { successed: true };
94
+ });
95
+ }
87
96
  /**
88
- * 组装请求参数
89
- * @param message
90
- * @param callChatOption
91
- * @param attach
92
- * @param _axiosOption
93
- */
97
+ * 获取设置的变量
98
+ * @returns
99
+ */
100
+ getVariables(params) {
101
+ return __awaiter(this, void 0, void 0, function* () {
102
+ const client = yield this.createClient();
103
+ const cozeParams = Object.assign({}, { bot_id: this.botid }, params);
104
+ const data = yield client.variables.retrieve(cozeParams);
105
+ if (data)
106
+ return Object.assign({ successed: true }, data);
107
+ return { successed: false, error: 'get variables failed' };
108
+ });
109
+ }
110
+ /**
111
+ * 组装请求参数
112
+ * @param message
113
+ * @param callChatOption
114
+ * @param attach
115
+ * @param _axiosOption
116
+ */
94
117
  getRequestStream(client, message, callChatOption = {}) {
95
118
  var _a;
96
119
  return __awaiter(this, void 0, void 0, function* () {
97
120
  //简单的对话请求
98
121
  const conversation_id = (_a = callChatOption.session_id) !== null && _a !== void 0 ? _a : yield this.createCoversation(client);
99
- if (!callChatOption.workflowid) {
122
+ if (!this.workflowid) {
100
123
  const req = {
101
124
  bot_id: this.botid,
102
125
  additional_messages: message,
@@ -109,7 +132,8 @@ class CorzBot extends gptbase_1.default {
109
132
  const worflowreq = {
110
133
  bot_id: this.botid,
111
134
  additional_messages: message,
112
- workflow_id: callChatOption.workflowid,
135
+ ext: callChatOption.ext,
136
+ workflow_id: this.workflowid,
113
137
  conversation_id,
114
138
  parameters: Object.assign({}, this.setting.customVariables || {}, callChatOption.customVariables || {}),
115
139
  };
@@ -117,11 +141,30 @@ class CorzBot extends gptbase_1.default {
117
141
  });
118
142
  }
119
143
  /**
120
- * 非流式传输聊天请求
121
- * @param chatText
122
- * @param callChatOption
123
- * @param _axiosOption
124
- */
144
+ * 同步调用的问答请求需要获取会话详情
145
+ * @param chatid
146
+ * @param conversation_id
147
+ */
148
+ getChatDetail(client, conversation_id, chatid) {
149
+ return __awaiter(this, void 0, void 0, function* () {
150
+ const maxWaitTime = 120000; // 最大等待120秒
151
+ const startTime = Date.now();
152
+ while ((Date.now() - startTime) < maxWaitTime) {
153
+ const chatinfo = yield client.chat.retrieve(conversation_id, chatid);
154
+ // 状态已经是完成了,可以去获取对话的内容了
155
+ if (chatinfo.status === api_1.ChatStatus.COMPLETED)
156
+ return { usage: chatinfo.usage, messages: yield client.chat.messages.list(conversation_id, chatid) };
157
+ yield new Promise(resolve => setTimeout(resolve, 1500)); // 等待1500ms
158
+ }
159
+ return null;
160
+ });
161
+ }
162
+ /**
163
+ * 非流式传输聊天请求
164
+ * @param chatText
165
+ * @param callChatOption
166
+ * @param _axiosOption
167
+ */
125
168
  chatRequest(message, callChatOption = {}, _axiosOption = {}) {
126
169
  return __awaiter(this, void 0, void 0, function* () {
127
170
  if (!message)
@@ -139,31 +182,29 @@ class CorzBot extends gptbase_1.default {
139
182
  ////如果参数中用的是Workflow,则调用对话流来输出结果
140
183
  ////否则用智能体的对话来输出结果
141
184
  const params = yield this.getRequestStream(client, message, callChatOption);
142
- const response = yield client.chat.createAndPoll(params);
143
- if (response.chat.status === api_1.ChatStatus.COMPLETED && response.messages) {
144
- const message = response.messages.filter(x => x.type === 'answer').map(item => ({
145
- role: item.role,
146
- type: item.type,
147
- content: item.content,
148
- }));
149
- const follow_up = response.messages.filter(x => x.type === 'follow_up').map(item => ({
150
- role: item.role,
151
- type: item.type,
152
- content: item.content,
153
- }));
154
- return { successed: true, message, follow_up, usage: response.chat.usage };
185
+ const response = !this.workflowid ? yield client.chat.create(params) : yield client.workflows.runs.create(params);
186
+ if (this.workflowid && response.msg === 'Success') {
187
+ const resp = response.data;
188
+ try {
189
+ return { successed: true, message: [{ role: 'assistant', type: 'answer', content: JSON.parse(resp).data }] };
190
+ }
191
+ catch (error) {
192
+ return { successed: true, message: [{ role: 'assistant', type: 'answer', content: resp }] };
193
+ }
155
194
  }
156
- return { successed: false, error: { message: '聊天未完成', status: response.chat.status } };
157
- // for await (const part of stream) {
158
- // if (part.event === ChatEventType.ERROR) return { successed: false, error: part.data.msg }
159
- // ////在流式传输中,提取相关推荐问题
160
- // if (part.event === ChatEventType.CONVERSATION_MESSAGE_COMPLETED) {
161
- // const { type, content, conversation_id } = part.data;
162
- // ///回答全部结束
163
- // if (type === 'answer') return { successed: true, message: [{ message: { content } }], session_id: conversation_id };
164
- // }
165
- // }
166
- //return { successed: false, error:'unknow' }
195
+ if (!this.workflowid && response.conversation_id && response.id) {
196
+ const ccd = response;
197
+ const chatData = yield this.getChatDetail(client, ccd.conversation_id, ccd.id);
198
+ if (chatData) {
199
+ const message = chatData.messages.filter(x => x.type === 'answer').map(item => ({
200
+ role: item.role,
201
+ type: item.type,
202
+ content: item.content,
203
+ }));
204
+ return { successed: true, message, usage: chatData.usage, session_id: ccd.conversation_id };
205
+ }
206
+ }
207
+ return { successed: false, error: { message: '聊天未完成' } };
167
208
  });
168
209
  }
169
210
  /**
@@ -173,13 +214,13 @@ class CorzBot extends gptbase_1.default {
173
214
  * @returns
174
215
  */
175
216
  parseDeepThinkingJson(content, status) {
176
- var _a;
177
- const thinkingEndIndex = content.indexOf("\"}");
178
217
  // const thinkingStartIndex = status === DeepThinkingStatus.Thinking ? content.indexOf("{\"process_msg") :
179
218
  // (status===DeepThinkingStatus.ReasonOutput ? content.indexOf("{\"reasoning_content") : content.indexOf("{\"card_resource")) ;
180
- const thinkingStartIndex = (_a = [content.indexOf("{\"process_msg"),
219
+ const tagLocation = [content.indexOf("{\"process_msg"),
181
220
  content.indexOf("{\"reasoning_content"),
182
- content.indexOf("{\"card_resource")].find(x => x >= 0)) !== null && _a !== void 0 ? _a : -1;
221
+ content.indexOf("{\"card_resource")].filter(x => x >= 0);
222
+ const thinkingStartIndex = tagLocation.length > 0 ? Math.min(...tagLocation) : -1;
223
+ const thinkingEndIndex = content.indexOf("\"}");
183
224
  // 如果没有找到相关的JSON内容,则直接返回
184
225
  if (thinkingStartIndex < 0)
185
226
  return { successed: true, content, status: DeepThinkingStatus.ThinkingOver };
@@ -195,14 +236,12 @@ class CorzBot extends gptbase_1.default {
195
236
  if (thinkingEndIndex >= 0)
196
237
  content = content.substring(thinkingEndIndex + 2);
197
238
  // 如果正常输出了卡片资源,并且json结束 card_resource 只有一个,所以一旦结束,则整个思考过程完毕
198
- if (status === DeepThinkingStatus.CardResource && thinkingEndIndex >= 0)
199
- status = DeepThinkingStatus.ThinkingOver;
239
+ // if (status === DeepThinkingStatus.ContentOutput && thinkingEndIndex >= 0) status = DeepThinkingStatus.ThinkingOver;
200
240
  // 判断整个思考过程是否到达等待卡片资源(有可能智能体输出不了卡片资源) reasoning_content 只有一个,所以一旦结束,则进入下一个阶段 card_resource
201
- if (status === DeepThinkingStatus.ReasonOutput && thinkingEndIndex >= 0)
202
- status = DeepThinkingStatus.CardResource;
241
+ //if (status === DeepThinkingStatus.ContentOutput && thinkingEndIndex >= 0) status = DeepThinkingStatus.ContentOutput;
203
242
  // 判断当前是否从前期思考切换到思考内容输出
204
- if (status === DeepThinkingStatus.Thinking && thinkingAction === DeepThinkingAction.content)
205
- status = DeepThinkingStatus.ReasonOutput;
243
+ if (status === DeepThinkingStatus.Thinking && thinkingAction !== DeepThinkingAction.process)
244
+ status = DeepThinkingStatus.ContentOutput;
206
245
  //if (status === DeepThinkingStatus.Thinking && content.indexOf("{\"reasoning_content") >= 0) status=DeepThinkingStatus.ReasonOutput;
207
246
  //const removeOutputContent = content.replace(originalContent!.substring(1, originalContent!.length - 2),"")
208
247
  let thinkingContent = originalContent === null || originalContent === void 0 ? void 0 : originalContent.substring(0, originalContent.length - 2);
@@ -212,15 +251,17 @@ class CorzBot extends gptbase_1.default {
212
251
  thinkingContent = thinkingContent.substring(this.lastThinkingMessage.textposition);
213
252
  }
214
253
  this.lastThinkingMessage = thinkingEndIndex >= 0 ? { action: thinkingAction, textposition: 0 } : { action: thinkingAction, textposition: outputLength };
215
- return { successed: true, thinking: {
254
+ return {
255
+ successed: true, thinking: {
216
256
  action: thinkingAction,
217
257
  text: thinkingContent,
218
258
  completed: thinkingEndIndex >= 0
219
- }, content, status };
259
+ }, content, status
260
+ };
220
261
  }
221
262
  catch (error) {
222
263
  // 如果在content之后发生了错误,可能该智能体输出不了卡片类型的数据,则输出的内容已经是正文了
223
- if (status === DeepThinkingStatus.CardResource) {
264
+ if (status === DeepThinkingStatus.ContentOutput) {
224
265
  status = DeepThinkingStatus.ThinkingOver;
225
266
  return { successed: true, content, status };
226
267
  }
@@ -239,7 +280,6 @@ class CorzBot extends gptbase_1.default {
239
280
  */
240
281
  chatRequestInStream(message, callChatOption = {}, attach, _axiosOption) {
241
282
  var _a, e_1, _b, _c;
242
- var _d, _e;
243
283
  return __awaiter(this, void 0, void 0, function* () {
244
284
  if (!message)
245
285
  this.emit('chaterror', { successed: false, error: 'no message in chat' });
@@ -257,13 +297,13 @@ class CorzBot extends gptbase_1.default {
257
297
  ////否则用智能体的对话来输出结果
258
298
  let requestid = Math.ceil(Math.random() * (new Date().getTime() * Math.random()) / 1000), index = 0;
259
299
  const params = yield this.getRequestStream(client, message, callChatOption);
260
- const stream = !callChatOption.workflowid ? client.chat.stream(params) : client.workflows.chat.stream(params);
261
- let deltaindex = 0, fullanswer = [], followup = [];
300
+ const stream = !this.workflowid ? client.chat.stream(params) : client.workflows.runs.stream(params);
301
+ let deltaindex = 0, fullanswer = [], followup = [], cardData = [];
262
302
  let deepThinking = '', thinkingStatus = DeepThinkingStatus.None, cardResource = ''; // 是否在深度思考中
263
303
  try {
264
- for (var _f = true, stream_1 = __asyncValues(stream), stream_1_1; stream_1_1 = yield stream_1.next(), _a = stream_1_1.done, !_a;) {
304
+ for (var _d = true, stream_1 = __asyncValues(stream), stream_1_1; stream_1_1 = yield stream_1.next(), _a = stream_1_1.done, !_a;) {
265
305
  _c = stream_1_1.value;
266
- _f = false;
306
+ _d = false;
267
307
  try {
268
308
  const part = _c;
269
309
  if (part.event === api_1.ChatEventType.ERROR)
@@ -281,18 +321,25 @@ class CorzBot extends gptbase_1.default {
281
321
  deepThinking += content;
282
322
  const result = this.parseDeepThinkingJson(deepThinking, thinkingStatus);
283
323
  if (result.successed) {
284
- // 如果不是卡片资源,则发送thinking事件,并更新thinkingStatus
285
- if (thinkingStatus !== DeepThinkingStatus.CardResource) {
324
+ const thinking = result.thinking;
325
+ if (thinking) {
286
326
  deepThinking = result.content;
287
- this.emit('chatthinking', result.thinking);
288
- }
289
- else if (thinkingStatus === DeepThinkingStatus.CardResource) {
290
- cardResource += (_d = result.thinking) === null || _d === void 0 ? void 0 : _d.text;
291
- // 卡片流结束,解析卡片资源数据
292
- if ((_e = result.thinking) === null || _e === void 0 ? void 0 : _e.completed) {
293
- const cardData = cardResource.replace(/[\x00-\x1F\x7F]/g, '').split('|').map((item) => (0, querystring_1.parse)(item));
294
- // 将卡片资源返回给客户端
295
- this.emit('chatcard', cardData);
327
+ if (thinking.action === DeepThinkingAction.card) {
328
+ cardResource += result.thinking.text;
329
+ // 卡片流结束,解析卡片资源数据
330
+ if (result.thinking.completed) {
331
+ const allCards = cardResource.replace(/[\x00-\x1F\x7F]/g, '').split('|');
332
+ for (const item of allCards) {
333
+ const cardinfo = (0, querystring_1.parse)(item);
334
+ if (cardinfo.type && cardinfo.tag)
335
+ cardData.push({ type: Number(cardinfo.type), tag: cardinfo.tag });
336
+ }
337
+ // 将卡片资源返回给客户端
338
+ this.emit('chatcard', cardData);
339
+ }
340
+ }
341
+ else {
342
+ this.emit('chatthinking', result.thinking);
296
343
  }
297
344
  }
298
345
  thinkingStatus = result.status;
@@ -318,21 +365,21 @@ class CorzBot extends gptbase_1.default {
318
365
  ///整个对话结束
319
366
  if (part.event === api_1.ChatEventType.CONVERSATION_CHAT_COMPLETED) {
320
367
  const { conversation_id } = part.data;
321
- let output = { successed: true, followup, type: 'answer', content_type: 'text', role: api_1.RoleType.Assistant, requestid, segment: null, text: fullanswer.join(''), index: index++, session_id: conversation_id };
368
+ let output = { successed: true, cards: cardData.length ? cardData : null, followup, type: 'answer', content_type: 'text', role: api_1.RoleType.Assistant, requestid, segment: null, text: fullanswer.join(''), index: index++, session_id: conversation_id };
322
369
  if (attach)
323
370
  output = Object.assign({}, output, attach);
324
371
  this.emit('chatdone', output);
325
372
  }
326
373
  }
327
374
  finally {
328
- _f = true;
375
+ _d = true;
329
376
  }
330
377
  }
331
378
  }
332
379
  catch (e_1_1) { e_1 = { error: e_1_1 }; }
333
380
  finally {
334
381
  try {
335
- if (!_f && !_a && (_b = stream_1.return)) yield _b.call(stream_1);
382
+ if (!_d && !_a && (_b = stream_1.return)) yield _b.call(stream_1);
336
383
  }
337
384
  finally { if (e_1) throw e_1.error; }
338
385
  }
package/dist/gptbase.d.ts CHANGED
@@ -23,6 +23,16 @@ export default abstract class GptBase extends EventEmitter {
23
23
  * @returns
24
24
  */
25
25
  createCoversation(_client?: any): Promise<string | null>;
26
+ /**
27
+ * 设置智能体的变量
28
+ * @returns
29
+ */
30
+ setVariables(_params: any): Promise<ApiResult>;
31
+ /**
32
+ * 获取智能体的变量
33
+ * @returns
34
+ */
35
+ getVariables(_params: any): Promise<any>;
26
36
  /**
27
37
  * 流式的聊天模式
28
38
  * @param chatText
package/dist/gptbase.js CHANGED
@@ -31,6 +31,22 @@ class GptBase extends events_1.EventEmitter {
31
31
  return null;
32
32
  });
33
33
  }
34
+ /**
35
+ * 设置智能体的变量
36
+ * @returns
37
+ */
38
+ setVariables(_params) {
39
+ return __awaiter(this, void 0, void 0, function* () {
40
+ return { successed: true };
41
+ });
42
+ }
43
+ /**
44
+ * 获取智能体的变量
45
+ * @returns
46
+ */
47
+ getVariables(_params) {
48
+ return __awaiter(this, void 0, void 0, function* () { return { successed: false }; });
49
+ }
34
50
  /**
35
51
  * 流式的聊天模式
36
52
  * @param chatText
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "doomiaichat",
3
- "version": "7.1.7",
3
+ "version": "7.1.9",
4
4
  "description": "Doomisoft OpenAI",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -17,7 +17,7 @@
17
17
  },
18
18
  "dependencies": {
19
19
  "@azure/openai": "^1.0.0-beta.11",
20
- "@coze/api": "^1.1.0",
20
+ "@coze/api": "^1.3.5",
21
21
  "axios": "^1.8.4",
22
22
  "openai": "^4.29.0"
23
23
  }
package/src/corzbot.ts CHANGED
@@ -1,50 +1,61 @@
1
1
  /**
2
2
  * 扣子智能体
3
3
  */
4
- import { CozeAPI,
4
+ import {
5
+ CozeAPI,
5
6
  COZE_CN_BASE_URL,
6
7
  ChatEventType,
7
- RoleType,
8
+ RoleType,
8
9
  StreamChatReq,
9
10
  EnterMessage,
10
11
  ChatWorkflowReq,
12
+ // CreateChatReq,
13
+ // ChatStatus,
14
+ VariableUpdateReq,
15
+ VariableRetrieveReq,
11
16
  CreateChatReq,
12
- ChatStatus} from '@coze/api';
17
+ RunWorkflowReq,
18
+ RunWorkflowData,
19
+ CreateChatData,
20
+ ChatStatus
21
+ } from '@coze/api';
13
22
  import GptBase from "./gptbase"
14
23
  import { CorzAuthorization } from './corzauthorization';
15
24
  import { parse } from 'querystring'
25
+ import { ApiResult } from './declare';
16
26
 
17
27
  // 定义深度思考的动作
18
28
  enum DeepThinkingAction {
19
- process = 'process_msg',
20
- content ='reasoning_content',
29
+ process = 'process_msg',
30
+ content = 'reasoning_content',
21
31
  card = 'card_resource'
22
32
  }
23
33
  // 定义深度思考的状态
24
34
  enum DeepThinkingStatus {
25
35
  None,
26
36
  Thinking,
27
- ReasonOutput,
28
- CardResource,
37
+ ContentOutput,
29
38
  ThinkingOver
30
39
  }
31
40
  // 智能体思考时输出的动作
32
-
41
+ type CardType = { type: number, tag: string }
33
42
  type TThinkingMessage = { action: string, textposition: number }
34
43
  export default class CorzBot extends GptBase {
35
44
  protected botid: string;
36
- private apiKey:string;
37
- private lastThinkingMessage: TThinkingMessage = { action: '', textposition:0 };
45
+ protected workflowid: string;
46
+ private apiKey: string;
47
+ private lastThinkingMessage: TThinkingMessage = { action: '', textposition: 0 };
38
48
  // protected client: CozeAPI;
39
49
  /**
40
50
  *
41
51
  * @param apikey 调用AI中台 的key
42
52
  * @param botid 智能体信息
43
53
  */
44
- constructor(private authorizationProvider: CorzAuthorization,private setting: any={}) {
54
+ constructor(private authorizationProvider: CorzAuthorization, private setting: any = {}) {
45
55
  super();
46
56
  ////初始化扣子客户端
47
57
  this.botid = this.setting['botid'] || this.setting['botID'];
58
+ this.workflowid = this.setting['workflowid'];
48
59
  this.apiKey = this.setting['apiKey'];
49
60
  }
50
61
  private async createClient(): Promise<CozeAPI> {
@@ -57,90 +68,125 @@ export default class CorzBot extends GptBase {
57
68
  /**
58
69
  * 发起一次会话
59
70
  */
60
- override async createCoversation(client?: CozeAPI):Promise<string|null>{
61
- try{
62
- const czApi = client?? await this.createClient();
63
- const result = await czApi.conversations.create({ bot_id: this.botid})
71
+ override async createCoversation(client?: CozeAPI): Promise<string | null> {
72
+ try {
73
+ const czApi = client ?? await this.createClient();
74
+ const params = this.botid ? { bot_id: this.botid } : {};
75
+ const result = await czApi.conversations.create(params)
64
76
  return result.id;
65
- }catch(error){
77
+ } catch (error) {
66
78
  console.error('createCoversation error in coze api');
67
79
  return null;
68
80
  }
69
81
  }
82
+
83
+ override async setVariables(params: any): Promise<ApiResult> {
84
+ const client = await this.createClient();
85
+ const cozeParams: VariableUpdateReq = Object.assign({}, this.botid ? { bot_id: this.botid } : {}, params);
86
+ client.variables.update(cozeParams)
87
+ return { successed: true };
88
+ }
70
89
  /**
71
- * 组装请求参数
72
- * @param message
73
- * @param callChatOption
74
- * @param attach
75
- * @param _axiosOption
76
- */
90
+ * 获取设置的变量
91
+ * @returns
92
+ */
93
+ override async getVariables(params: any): Promise<any> {
94
+ const client = await this.createClient();
95
+ const cozeParams: VariableRetrieveReq = Object.assign({}, { bot_id: this.botid }, params);
96
+ const data = await client.variables.retrieve(cozeParams);
97
+ if (data) return { successed: true, ...data }
98
+ return { successed: false, error: 'get variables failed' };
99
+ }
100
+ /**
101
+ * 组装请求参数
102
+ * @param message
103
+ * @param callChatOption
104
+ * @param attach
105
+ * @param _axiosOption
106
+ */
77
107
  async getRequestStream<T>(client: CozeAPI, message: EnterMessage[], callChatOption: any = {}): Promise<T> {
78
108
  //简单的对话请求
79
109
  const conversation_id = callChatOption.session_id ?? await this.createCoversation(client);
80
- if (!callChatOption.workflowid) {
110
+ if (!this.workflowid) {
81
111
  const req: StreamChatReq = {
82
112
  bot_id: this.botid,
83
113
  additional_messages: message,
84
114
  user_id: callChatOption.userid || callChatOption.cozeUserID,
85
115
  conversation_id
86
116
  }
87
- req.custom_variables = Object.assign({}, this.setting.customVariables || {}, callChatOption.customVariables || {});
117
+ req.custom_variables = Object.assign({}, this.setting.customVariables || {}, callChatOption.customVariables || {});
88
118
  return req as T;
89
119
  }
90
120
  const worflowreq: ChatWorkflowReq = {
91
121
  bot_id: this.botid,
92
122
  additional_messages: message,
93
- workflow_id: callChatOption.workflowid,
123
+ ext: callChatOption.ext,
124
+ workflow_id: this.workflowid,//callChatOption.workflowid,
94
125
  conversation_id,
95
- parameters: Object.assign({}, this.setting.customVariables || {}, callChatOption.customVariables || {}),
126
+ parameters: Object.assign({}, this.setting.customVariables || {}, callChatOption.customVariables || {}),
96
127
  }
97
128
  return worflowreq as T;
98
129
  }
99
130
  /**
100
- * 非流式传输聊天请求
101
- * @param chatText
102
- * @param callChatOption
103
- * @param _axiosOption
104
- */
105
- public async chatRequest(message: any[]|string, callChatOption: any={}, _axiosOption: any = {}): Promise<any> {
131
+ * 同步调用的问答请求需要获取会话详情
132
+ * @param chatid
133
+ * @param conversation_id
134
+ */
135
+ private async getChatDetail(client: CozeAPI, conversation_id: string, chatid: string) {
136
+ const maxWaitTime = 120000; // 最大等待120秒
137
+ const startTime = Date.now();
138
+ while ((Date.now() - startTime) < maxWaitTime) {
139
+ const chatinfo = await client.chat.retrieve(conversation_id, chatid);
140
+ // 状态已经是完成了,可以去获取对话的内容了
141
+ if (chatinfo.status === ChatStatus.COMPLETED) return { usage: chatinfo.usage, messages: await client.chat.messages.list(conversation_id, chatid)};
142
+ await new Promise(resolve => setTimeout(resolve, 1500)); // 等待1500ms
143
+ }
144
+ return null;
145
+ }
146
+ /**
147
+ * 非流式传输聊天请求
148
+ * @param chatText
149
+ * @param callChatOption
150
+ * @param _axiosOption
151
+ */
152
+ public async chatRequest(message: any[] | string, callChatOption: any = {}, _axiosOption: any = {}): Promise<any> {
106
153
  if (!message) this.emit('chaterror', { successed: false, error: 'no message in chat' });
107
154
  ///如果是字符,则组装成API需要的消息
108
155
  if (typeof message === 'string') message = [
109
156
  {
110
157
  role: RoleType.User,
111
- content_type:'text' ,
158
+ content_type: 'text',
112
159
  content: message
113
160
  }
114
161
  ];
115
162
  const client = await this.createClient();
163
+
116
164
  ////如果参数中用的是Workflow,则调用对话流来输出结果
117
165
  ////否则用智能体的对话来输出结果
118
- const params = await this.getRequestStream(client,message, callChatOption);
119
- const response = await client.chat.createAndPoll(params as CreateChatReq);
120
- if (response.chat.status === ChatStatus.COMPLETED && response.messages) {
121
- const message = response.messages.filter(x=>x.type==='answer').map(item => ({
122
- role: item.role,
123
- type: item.type,
124
- content: item.content,
125
- }));
126
- const follow_up = response.messages.filter(x => x.type === 'follow_up').map(item => ({
127
- role: item.role,
128
- type: item.type,
129
- content: item.content,
130
- }));
131
- return { successed: true, message, follow_up,usage: response.chat.usage };
166
+ const params = await this.getRequestStream(client, message, callChatOption);
167
+ const response = !this.workflowid ? await client.chat.create(params as CreateChatReq) : await client.workflows.runs.create(params as RunWorkflowReq);
168
+ if (this.workflowid && (response as RunWorkflowData).msg === 'Success') {
169
+ const resp = (response as RunWorkflowData).data;
170
+ try {
171
+ return { successed: true, message: [{ role: 'assistant', type:'answer', content: JSON.parse(resp).data }]};
172
+ } catch (error) {
173
+ return { successed: true, message: [{ role: 'assistant', type: 'answer', content: resp }] };
174
+ }
132
175
  }
133
- return { successed: false, error: { message: '聊天未完成', status: response.chat.status } };
134
- // for await (const part of stream) {
135
- // if (part.event === ChatEventType.ERROR) return { successed: false, error: part.data.msg }
136
- // ////在流式传输中,提取相关推荐问题
137
- // if (part.event === ChatEventType.CONVERSATION_MESSAGE_COMPLETED) {
138
- // const { type, content, conversation_id } = part.data;
139
- // ///回答全部结束
140
- // if (type === 'answer') return { successed: true, message: [{ message: { content } }], session_id: conversation_id };
141
- // }
142
- // }
143
- //return { successed: false, error:'unknow' }
176
+ if (!this.workflowid && (response as CreateChatData).conversation_id && (response as CreateChatData).id) {
177
+ const ccd = response as CreateChatData;
178
+ const chatData = await this.getChatDetail(client, ccd.conversation_id, ccd.id);
179
+ if (chatData){
180
+ const message = chatData.messages.filter(x => x.type === 'answer').map(item => ({
181
+ role: item.role,
182
+ type: item.type,
183
+ content: item.content,
184
+ }));
185
+ return { successed: true, message, usage: chatData.usage,session_id:ccd.conversation_id };
186
+ }
187
+ }
188
+ return { successed: false, error: { message: '聊天未完成' } };
189
+
144
190
  }
145
191
  /**
146
192
  * 解析深度思考的JSON内容
@@ -148,53 +194,58 @@ export default class CorzBot extends GptBase {
148
194
  * @param status
149
195
  * @returns
150
196
  */
151
- private parseDeepThinkingJson(content: string,status: DeepThinkingStatus) {
152
- const thinkingEndIndex = content.indexOf("\"}");
197
+ private parseDeepThinkingJson(content: string, status: DeepThinkingStatus) {
198
+
153
199
  // const thinkingStartIndex = status === DeepThinkingStatus.Thinking ? content.indexOf("{\"process_msg") :
154
200
  // (status===DeepThinkingStatus.ReasonOutput ? content.indexOf("{\"reasoning_content") : content.indexOf("{\"card_resource")) ;
155
- const thinkingStartIndex = [content.indexOf("{\"process_msg"),
156
- content.indexOf("{\"reasoning_content"),
157
- content.indexOf("{\"card_resource")].find(x=>x>=0)??-1;
201
+ const tagLocation = [content.indexOf("{\"process_msg"),
202
+ content.indexOf("{\"reasoning_content"),
203
+ content.indexOf("{\"card_resource")].filter(x => x >= 0);
204
+ const thinkingStartIndex = tagLocation.length > 0 ? Math.min(...tagLocation) : -1;
205
+ const thinkingEndIndex = content.indexOf("\"}");
158
206
  // 如果没有找到相关的JSON内容,则直接返回
159
- if (thinkingStartIndex < 0) return { successed: true, content, status: DeepThinkingStatus.ThinkingOver};
207
+ if (thinkingStartIndex < 0) return { successed: true, content, status: DeepThinkingStatus.ThinkingOver };
160
208
  let jsonStr = null;
161
- try{
162
- jsonStr = content.substring(thinkingStartIndex, thinkingEndIndex >= 0 ? thinkingEndIndex : undefined) +"\"}";
209
+ try {
210
+ jsonStr = content.substring(thinkingStartIndex, thinkingEndIndex >= 0 ? thinkingEndIndex : undefined) + "\"}";
163
211
  // 转换JSON的时候需要将非法字符过滤掉
164
212
  const thinkingObject = JSON.parse(jsonStr.replace(/[\x00-\x1F\x7F]/g, ''));
165
213
  const thinkingAction = Object.keys(thinkingObject)[0];
166
214
  // 需要将内容的原文返回
167
215
  const originalContent = jsonStr.split('":"')[1];
168
216
  // 如果正确的解析JSON,并且当前有包含JSON结束的字符,则把当前思考的JSON内容替换掉
169
- if (thinkingEndIndex >= 0) content = content.substring(thinkingEndIndex+2);
217
+ if (thinkingEndIndex >= 0) content = content.substring(thinkingEndIndex + 2);
170
218
  // 如果正常输出了卡片资源,并且json结束 card_resource 只有一个,所以一旦结束,则整个思考过程完毕
171
- if (status === DeepThinkingStatus.CardResource && thinkingEndIndex >= 0) status = DeepThinkingStatus.ThinkingOver;
219
+ // if (status === DeepThinkingStatus.ContentOutput && thinkingEndIndex >= 0) status = DeepThinkingStatus.ThinkingOver;
172
220
  // 判断整个思考过程是否到达等待卡片资源(有可能智能体输出不了卡片资源) reasoning_content 只有一个,所以一旦结束,则进入下一个阶段 card_resource
173
- if (status === DeepThinkingStatus.ReasonOutput && thinkingEndIndex >= 0) status = DeepThinkingStatus.CardResource;
221
+ //if (status === DeepThinkingStatus.ContentOutput && thinkingEndIndex >= 0) status = DeepThinkingStatus.ContentOutput;
174
222
  // 判断当前是否从前期思考切换到思考内容输出
175
- if (status === DeepThinkingStatus.Thinking && thinkingAction === DeepThinkingAction.content) status = DeepThinkingStatus.ReasonOutput;
223
+ if (status === DeepThinkingStatus.Thinking && thinkingAction !== DeepThinkingAction.process)
224
+ status = DeepThinkingStatus.ContentOutput;
176
225
  //if (status === DeepThinkingStatus.Thinking && content.indexOf("{\"reasoning_content") >= 0) status=DeepThinkingStatus.ReasonOutput;
177
226
  //const removeOutputContent = content.replace(originalContent!.substring(1, originalContent!.length - 2),"")
178
227
  let thinkingContent = originalContent?.substring(0, originalContent.length - 2)
179
228
  const outputLength = thinkingContent?.length || 0;
180
-
229
+
181
230
  // 用lastThinkingMessage来记录上一次的思考内容,避免重复输出内容,导致的网络传输内容过多
182
- if (this.lastThinkingMessage.action === thinkingAction && this.lastThinkingMessage.textposition){
231
+ if (this.lastThinkingMessage.action === thinkingAction && this.lastThinkingMessage.textposition) {
183
232
  thinkingContent = thinkingContent!.substring(this.lastThinkingMessage.textposition)
184
233
  }
185
- this.lastThinkingMessage = thinkingEndIndex >= 0 ? { action: thinkingAction!, textposition:0 } : { action: thinkingAction!, textposition: outputLength }
234
+ this.lastThinkingMessage = thinkingEndIndex >= 0 ? { action: thinkingAction!, textposition: 0 } : { action: thinkingAction!, textposition: outputLength }
186
235
 
187
- return { successed: true,thinking:{
188
- action: thinkingAction,
189
- text: thinkingContent,//Object.values(thinkingObject)[0]
190
- completed: thinkingEndIndex >= 0
191
- }, content, status}
236
+ return {
237
+ successed: true, thinking: {
238
+ action: thinkingAction,
239
+ text: thinkingContent,//Object.values(thinkingObject)[0]
240
+ completed: thinkingEndIndex >= 0
241
+ }, content, status
242
+ }
192
243
  }
193
- catch(error){
244
+ catch (error) {
194
245
  // 如果在content之后发生了错误,可能该智能体输出不了卡片类型的数据,则输出的内容已经是正文了
195
- if (status === DeepThinkingStatus.CardResource) {
246
+ if (status === DeepThinkingStatus.ContentOutput) {
196
247
  status = DeepThinkingStatus.ThinkingOver;
197
- return {successed: true, content, status};
248
+ return { successed: true, content, status };
198
249
  }
199
250
  console.error('解析JSON出错了:', jsonStr, status)
200
251
  // 当前解析出错,等待下一次解析
@@ -209,7 +260,7 @@ export default class CorzBot extends GptBase {
209
260
  * @param _axiosOption
210
261
  * @returns
211
262
  */
212
- override async chatRequestInStream(message: any[]|string, callChatOption: any={}, attach?: any, _axiosOption?: any): Promise<any> {
263
+ override async chatRequestInStream(message: any[] | string, callChatOption: any = {}, attach?: any, _axiosOption?: any): Promise<any> {
213
264
  if (!message) this.emit('chaterror', { successed: false, error: 'no message in chat' });
214
265
  ///如果是字符,则组装成API需要的消息
215
266
  if (typeof message === 'string') message = [
@@ -222,38 +273,44 @@ export default class CorzBot extends GptBase {
222
273
  const client = await this.createClient();
223
274
  ////如果参数中用的是Workflow,则调用对话流来输出结果
224
275
  ////否则用智能体的对话来输出结果
225
- let requestid = Math.ceil(Math.random() * (new Date().getTime() * Math.random()) / 1000), index=0;
226
- const params = await this.getRequestStream(client,message, callChatOption);
227
- const stream = !callChatOption.workflowid? client.chat.stream(params as StreamChatReq) : client.workflows.chat.stream(params as ChatWorkflowReq);
228
- let deltaindex = 0, fullanswer: string[] = [], followup: string[] = [];
229
- let deepThinking = '', thinkingStatus = DeepThinkingStatus.None,cardResource=''; // 是否在深度思考中
276
+ let requestid = Math.ceil(Math.random() * (new Date().getTime() * Math.random()) / 1000), index = 0;
277
+ const params = await this.getRequestStream(client, message, callChatOption);
278
+ const stream = !this.workflowid ? client.chat.stream(params as StreamChatReq) : client.workflows.runs.stream(params as RunWorkflowReq);
279
+ let deltaindex = 0, fullanswer: string[] = [], followup: string[] = [], cardData: CardType[] = [];
280
+ let deepThinking = '', thinkingStatus = DeepThinkingStatus.None, cardResource = ''; // 是否在深度思考中
230
281
  for await (const part of stream) {
231
282
  if (part.event === ChatEventType.ERROR) return this.emit('chaterror', { successed: false, error: 'call failed' });
232
283
  if (part.event === ChatEventType.CONVERSATION_MESSAGE_DELTA) {
233
- let { conversation_id, content_type,type, role, content } = part.data;
284
+ let { conversation_id, content_type, type, role, content } = part.data;
234
285
  // 如果存在深度思考,则一开始就会带有相关的关键信息
235
286
  if (deltaindex === 0 && content.startsWith("{\"process_msg")) {
236
- thinkingStatus=DeepThinkingStatus.Thinking;
287
+ thinkingStatus = DeepThinkingStatus.Thinking;
237
288
  deltaindex++;
238
289
  }
239
290
  // 如果在深度思考中,则不输出消息
240
- if (thinkingStatus !== DeepThinkingStatus.None
291
+ if (thinkingStatus !== DeepThinkingStatus.None
241
292
  && thinkingStatus !== DeepThinkingStatus.ThinkingOver
242
- ){
293
+ ) {
243
294
  deepThinking += content;
244
295
  const result = this.parseDeepThinkingJson(deepThinking, thinkingStatus)
245
- if (result.successed ){
246
- // 如果不是卡片资源,则发送thinking事件,并更新thinkingStatus
247
- if(thinkingStatus !== DeepThinkingStatus.CardResource){
296
+ if (result.successed) {
297
+ const thinking = result.thinking;
298
+ if (thinking) {
248
299
  deepThinking = result.content;
249
- this.emit('chatthinking', result.thinking);
250
- } else if (thinkingStatus === DeepThinkingStatus.CardResource) {
251
- cardResource += result.thinking?.text;
252
- // 卡片流结束,解析卡片资源数据
253
- if (result.thinking?.completed){
254
- const cardData:any[] = cardResource.replace(/[\x00-\x1F\x7F]/g, '').split('|').map((item:string)=>parse(item));
255
- // 将卡片资源返回给客户端
256
- this.emit('chatcard', cardData);
300
+ if (thinking.action === DeepThinkingAction.card) {
301
+ cardResource += result.thinking.text;
302
+ // 卡片流结束,解析卡片资源数据
303
+ if (result.thinking.completed) {
304
+ const allCards = cardResource.replace(/[\x00-\x1F\x7F]/g, '').split('|')
305
+ for (const item of allCards) {
306
+ const cardinfo: any = parse(item);
307
+ if (cardinfo.type && cardinfo.tag) cardData.push({ type: Number(cardinfo.type), tag: cardinfo.tag })
308
+ }
309
+ // 将卡片资源返回给客户端
310
+ this.emit('chatcard', cardData);
311
+ }
312
+ } else {
313
+ this.emit('chatthinking', result.thinking);
257
314
  }
258
315
  }
259
316
  thinkingStatus = result.status;
@@ -270,13 +327,13 @@ export default class CorzBot extends GptBase {
270
327
  }
271
328
  ////在流式传输中,提取相关推荐问题
272
329
  if (part.event === ChatEventType.CONVERSATION_MESSAGE_COMPLETED) {
273
- const { type, content} = part.data;
274
- if (type ==='follow_up') followup.push(content);
330
+ const { type, content } = part.data;
331
+ if (type === 'follow_up') followup.push(content);
275
332
  }
276
333
  ///整个对话结束
277
334
  if (part.event === ChatEventType.CONVERSATION_CHAT_COMPLETED) {
278
- const { conversation_id} = part.data;
279
- let output = { successed: true, followup, type: 'answer', content_type: 'text', role:RoleType.Assistant, requestid, segment: null, text: fullanswer.join(''), index: index++, session_id: conversation_id };
335
+ const { conversation_id } = part.data;
336
+ let output = { successed: true, cards: cardData.length ? cardData : null, followup, type: 'answer', content_type: 'text', role: RoleType.Assistant, requestid, segment: null, text: fullanswer.join(''), index: index++, session_id: conversation_id };
280
337
  if (attach) output = Object.assign({}, output, attach);
281
338
  this.emit('chatdone', output)
282
339
  }
package/src/gptbase.ts CHANGED
@@ -28,6 +28,19 @@ export default abstract class GptBase extends EventEmitter {
28
28
  async createCoversation(_client?:any):Promise<string|null> {
29
29
  return null;
30
30
  }
31
+
32
+ /**
33
+ * 设置智能体的变量
34
+ * @returns
35
+ */
36
+ async setVariables(_params: any):Promise<ApiResult> {
37
+ return { successed: true };
38
+ }
39
+ /**
40
+ * 获取智能体的变量
41
+ * @returns
42
+ */
43
+ async getVariables(_params: any): Promise<any> { return {successed: false}}
31
44
  /**
32
45
  * 流式的聊天模式
33
46
  * @param chatText