doomiaichat 7.0.4 → 7.1.4
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/corzauthorization.d.ts +19 -0
- package/dist/corzauthorization.js +79 -0
- package/dist/corzbot.d.ts +55 -0
- package/dist/corzbot.js +296 -0
- package/dist/deepseek.d.ts +5 -0
- package/dist/deepseek.js +16 -0
- package/dist/gptprovider.d.ts +2 -0
- package/dist/gptprovider.js +16 -0
- package/package.json +3 -2
- package/src/corzauthorization.ts +59 -0
- package/src/corzbot.ts +242 -0
- package/src/deepseek.ts +11 -0
- package/src/gptprovider.ts +16 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export declare class CorzAuthorization {
|
|
2
|
+
private appid;
|
|
3
|
+
private accessToken;
|
|
4
|
+
private expiresAt;
|
|
5
|
+
private pemfile;
|
|
6
|
+
private secret;
|
|
7
|
+
private sessionName;
|
|
8
|
+
constructor(appid: string, setting: Record<string, any>);
|
|
9
|
+
/**
|
|
10
|
+
* 获取授权令牌
|
|
11
|
+
* @returns
|
|
12
|
+
*/
|
|
13
|
+
getAccessToken(): Promise<string | null>;
|
|
14
|
+
/**
|
|
15
|
+
* 进行授权
|
|
16
|
+
* @returns
|
|
17
|
+
*/
|
|
18
|
+
private doAuthorize;
|
|
19
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
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
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.CorzAuthorization = void 0;
|
|
16
|
+
const fs_1 = __importDefault(require("fs"));
|
|
17
|
+
const path_1 = __importDefault(require("path"));
|
|
18
|
+
const api_1 = require("@coze/api");
|
|
19
|
+
class CorzAuthorization {
|
|
20
|
+
constructor(appid, setting) {
|
|
21
|
+
this.appid = appid;
|
|
22
|
+
this.expiresAt = 0;
|
|
23
|
+
this.secret = setting["keyid"];
|
|
24
|
+
this.pemfile = setting["pemfile"] || "private.pem";
|
|
25
|
+
this.sessionName = setting["sessionName"] || "default";
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* 获取授权令牌
|
|
29
|
+
* @returns
|
|
30
|
+
*/
|
|
31
|
+
getAccessToken() {
|
|
32
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
33
|
+
// 检查令牌是否存在且未过期,如果有效直接放回
|
|
34
|
+
if (this.accessToken && Date.now() < this.expiresAt)
|
|
35
|
+
return this.accessToken;
|
|
36
|
+
// 开始新的授权
|
|
37
|
+
const result = yield this.doAuthorize();
|
|
38
|
+
if (!result.successed)
|
|
39
|
+
return null;
|
|
40
|
+
// 缓存授权令牌和过期时间
|
|
41
|
+
this.accessToken = result.accessToken;
|
|
42
|
+
// 将 expires_in 转换为绝对时间戳
|
|
43
|
+
this.expiresAt = result.expires_in * 1000; // 将秒转换为毫秒
|
|
44
|
+
return this.accessToken;
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* 进行授权
|
|
49
|
+
* @returns
|
|
50
|
+
*/
|
|
51
|
+
doAuthorize() {
|
|
52
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
53
|
+
try {
|
|
54
|
+
// 提取您的 COZE API 授权参数
|
|
55
|
+
//const keyid = "H7rAk-5s0TPOs9-rXnCr7pvkPhpJZGArT__UuMyhbkg";
|
|
56
|
+
const aud = "api.coze.cn";
|
|
57
|
+
// 读取私钥
|
|
58
|
+
const fileFullPath = path_1.default.join(process.cwd(), this.pemfile);
|
|
59
|
+
if (!fs_1.default.existsSync(fileFullPath))
|
|
60
|
+
return { successed: false, error: `${fileFullPath} not existed` };
|
|
61
|
+
const privateKey = fs_1.default.readFileSync(fileFullPath).toString();
|
|
62
|
+
// 获取JWT令牌
|
|
63
|
+
const result = yield (0, api_1.getJWTToken)({
|
|
64
|
+
baseURL: api_1.COZE_CN_BASE_URL,
|
|
65
|
+
appId: this.appid,
|
|
66
|
+
aud,
|
|
67
|
+
keyid: this.secret,
|
|
68
|
+
privateKey,
|
|
69
|
+
sessionName: this.sessionName,
|
|
70
|
+
});
|
|
71
|
+
return { successed: true, accessToken: result.access_token, expires_in: result.expires_in };
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
return { successed: true, error };
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
exports.CorzAuthorization = CorzAuthorization;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 扣子智能体
|
|
3
|
+
*/
|
|
4
|
+
import { CozeAPI, EnterMessage } from '@coze/api';
|
|
5
|
+
import GptBase from "./gptbase";
|
|
6
|
+
import { CorzAuthorization } from './corzauthorization';
|
|
7
|
+
export default class CorzBot extends GptBase {
|
|
8
|
+
private authorizationProvider;
|
|
9
|
+
private setting;
|
|
10
|
+
protected botid: string;
|
|
11
|
+
private apiKey;
|
|
12
|
+
private lastThinkingMessage;
|
|
13
|
+
/**
|
|
14
|
+
*
|
|
15
|
+
* @param apikey 调用AI中台 的key
|
|
16
|
+
* @param botid 智能体信息
|
|
17
|
+
*/
|
|
18
|
+
constructor(authorizationProvider: CorzAuthorization, setting?: any);
|
|
19
|
+
private createClient;
|
|
20
|
+
/**
|
|
21
|
+
* 发起一次会话
|
|
22
|
+
*/
|
|
23
|
+
private createCoversation;
|
|
24
|
+
/**
|
|
25
|
+
* 组装请求参数
|
|
26
|
+
* @param message
|
|
27
|
+
* @param callChatOption
|
|
28
|
+
* @param attach
|
|
29
|
+
* @param _axiosOption
|
|
30
|
+
*/
|
|
31
|
+
getRequestStream<T>(client: CozeAPI, message: EnterMessage[], callChatOption?: any): Promise<T>;
|
|
32
|
+
/**
|
|
33
|
+
* 非流式传输聊天请求
|
|
34
|
+
* @param chatText
|
|
35
|
+
* @param callChatOption
|
|
36
|
+
* @param _axiosOption
|
|
37
|
+
*/
|
|
38
|
+
chatRequest(message: any[] | string, callChatOption?: any, _axiosOption?: any): Promise<any>;
|
|
39
|
+
/**
|
|
40
|
+
* 解析深度思考的JSON内容
|
|
41
|
+
* @param content
|
|
42
|
+
* @param status
|
|
43
|
+
* @returns
|
|
44
|
+
*/
|
|
45
|
+
private parseDeepThinkingJson;
|
|
46
|
+
/**
|
|
47
|
+
* 流式传输聊天请求
|
|
48
|
+
* @param chatText
|
|
49
|
+
* @param callChatOption
|
|
50
|
+
* @param attach
|
|
51
|
+
* @param _axiosOption
|
|
52
|
+
* @returns
|
|
53
|
+
*/
|
|
54
|
+
chatRequestInStream(message: any[] | string, callChatOption?: any, attach?: any, _axiosOption?: any): Promise<any>;
|
|
55
|
+
}
|
package/dist/corzbot.js
ADDED
|
@@ -0,0 +1,296 @@
|
|
|
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
|
+
var __asyncValues = (this && this.__asyncValues) || function (o) {
|
|
12
|
+
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
13
|
+
var m = o[Symbol.asyncIterator], i;
|
|
14
|
+
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
|
|
15
|
+
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
|
|
16
|
+
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
|
|
17
|
+
};
|
|
18
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
19
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
20
|
+
};
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
/**
|
|
23
|
+
* 扣子智能体
|
|
24
|
+
*/
|
|
25
|
+
const api_1 = require("@coze/api");
|
|
26
|
+
const gptbase_1 = __importDefault(require("./gptbase"));
|
|
27
|
+
var DeepThinkingStatus;
|
|
28
|
+
(function (DeepThinkingStatus) {
|
|
29
|
+
DeepThinkingStatus[DeepThinkingStatus["None"] = 0] = "None";
|
|
30
|
+
DeepThinkingStatus[DeepThinkingStatus["Thinking"] = 1] = "Thinking";
|
|
31
|
+
DeepThinkingStatus[DeepThinkingStatus["ReasonOutput"] = 2] = "ReasonOutput";
|
|
32
|
+
DeepThinkingStatus[DeepThinkingStatus["ThinkingOver"] = 3] = "ThinkingOver";
|
|
33
|
+
})(DeepThinkingStatus || (DeepThinkingStatus = {}));
|
|
34
|
+
class CorzBot extends gptbase_1.default {
|
|
35
|
+
// protected client: CozeAPI;
|
|
36
|
+
/**
|
|
37
|
+
*
|
|
38
|
+
* @param apikey 调用AI中台 的key
|
|
39
|
+
* @param botid 智能体信息
|
|
40
|
+
*/
|
|
41
|
+
constructor(authorizationProvider, setting = {}) {
|
|
42
|
+
super();
|
|
43
|
+
this.authorizationProvider = authorizationProvider;
|
|
44
|
+
this.setting = setting;
|
|
45
|
+
this.lastThinkingMessage = { action: '', textposition: 0 };
|
|
46
|
+
////初始化扣子客户端
|
|
47
|
+
this.botid = this.setting['botid'];
|
|
48
|
+
this.apiKey = this.setting['apiKey'];
|
|
49
|
+
}
|
|
50
|
+
createClient() {
|
|
51
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
52
|
+
// 存在AppKey则使用AppKey进行认证
|
|
53
|
+
if (this.apiKey)
|
|
54
|
+
return new api_1.CozeAPI({ baseURL: api_1.COZE_CN_BASE_URL, token: this.apiKey });
|
|
55
|
+
const accessToken = yield this.authorizationProvider.getAccessToken();
|
|
56
|
+
if (!accessToken)
|
|
57
|
+
throw new Error('get access token failed');
|
|
58
|
+
return new api_1.CozeAPI({ baseURL: api_1.COZE_CN_BASE_URL, token: accessToken });
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* 发起一次会话
|
|
63
|
+
*/
|
|
64
|
+
createCoversation(client) {
|
|
65
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
66
|
+
const result = yield client.conversations.create({
|
|
67
|
+
bot_id: this.botid,
|
|
68
|
+
});
|
|
69
|
+
return result.id;
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* 组装请求参数
|
|
74
|
+
* @param message
|
|
75
|
+
* @param callChatOption
|
|
76
|
+
* @param attach
|
|
77
|
+
* @param _axiosOption
|
|
78
|
+
*/
|
|
79
|
+
getRequestStream(client, message, callChatOption = {}) {
|
|
80
|
+
var _a;
|
|
81
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
82
|
+
//简单的对话请求
|
|
83
|
+
const conversation_id = (_a = callChatOption.session_id) !== null && _a !== void 0 ? _a : yield this.createCoversation(client);
|
|
84
|
+
if (!callChatOption.workflowid) {
|
|
85
|
+
const req = {
|
|
86
|
+
bot_id: this.botid,
|
|
87
|
+
additional_messages: message,
|
|
88
|
+
user_id: callChatOption.userid || callChatOption.cozeUserID,
|
|
89
|
+
conversation_id
|
|
90
|
+
};
|
|
91
|
+
req.custom_variables = Object.assign({}, this.setting.customVariables || {}, callChatOption.customVariables || {});
|
|
92
|
+
return req;
|
|
93
|
+
}
|
|
94
|
+
const worflowreq = {
|
|
95
|
+
bot_id: this.botid,
|
|
96
|
+
additional_messages: message,
|
|
97
|
+
workflow_id: callChatOption.workflowid,
|
|
98
|
+
conversation_id,
|
|
99
|
+
parameters: Object.assign({}, this.setting.customVariables || {}, callChatOption.customVariables || {}),
|
|
100
|
+
};
|
|
101
|
+
return worflowreq;
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* 非流式传输聊天请求
|
|
106
|
+
* @param chatText
|
|
107
|
+
* @param callChatOption
|
|
108
|
+
* @param _axiosOption
|
|
109
|
+
*/
|
|
110
|
+
chatRequest(message, callChatOption = {}, _axiosOption = {}) {
|
|
111
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
112
|
+
if (!message)
|
|
113
|
+
this.emit('chaterror', { successed: false, error: 'no message in chat' });
|
|
114
|
+
///如果是字符,则组装成API需要的消息
|
|
115
|
+
if (typeof message === 'string')
|
|
116
|
+
message = [
|
|
117
|
+
{
|
|
118
|
+
role: api_1.RoleType.User,
|
|
119
|
+
content_type: 'text',
|
|
120
|
+
content: message
|
|
121
|
+
}
|
|
122
|
+
];
|
|
123
|
+
const client = yield this.createClient();
|
|
124
|
+
////如果参数中用的是Workflow,则调用对话流来输出结果
|
|
125
|
+
////否则用智能体的对话来输出结果
|
|
126
|
+
const params = yield this.getRequestStream(client, message, callChatOption);
|
|
127
|
+
const response = yield client.chat.createAndPoll(params);
|
|
128
|
+
if (response.chat.status === api_1.ChatStatus.COMPLETED && response.messages) {
|
|
129
|
+
const message = response.messages.filter(x => x.type === 'answer').map(item => ({
|
|
130
|
+
role: item.role,
|
|
131
|
+
type: item.type,
|
|
132
|
+
content: item.content,
|
|
133
|
+
}));
|
|
134
|
+
const follow_up = response.messages.filter(x => x.type === 'follow_up').map(item => ({
|
|
135
|
+
role: item.role,
|
|
136
|
+
type: item.type,
|
|
137
|
+
content: item.content,
|
|
138
|
+
}));
|
|
139
|
+
return { successed: true, message, follow_up, usage: response.chat.usage };
|
|
140
|
+
}
|
|
141
|
+
return { successed: false, error: { message: '聊天未完成', status: response.chat.status } };
|
|
142
|
+
// for await (const part of stream) {
|
|
143
|
+
// if (part.event === ChatEventType.ERROR) return { successed: false, error: part.data.msg }
|
|
144
|
+
// ////在流式传输中,提取相关推荐问题
|
|
145
|
+
// if (part.event === ChatEventType.CONVERSATION_MESSAGE_COMPLETED) {
|
|
146
|
+
// const { type, content, conversation_id } = part.data;
|
|
147
|
+
// ///回答全部结束
|
|
148
|
+
// if (type === 'answer') return { successed: true, message: [{ message: { content } }], session_id: conversation_id };
|
|
149
|
+
// }
|
|
150
|
+
// }
|
|
151
|
+
//return { successed: false, error:'unknow' }
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* 解析深度思考的JSON内容
|
|
156
|
+
* @param content
|
|
157
|
+
* @param status
|
|
158
|
+
* @returns
|
|
159
|
+
*/
|
|
160
|
+
parseDeepThinkingJson(content, status) {
|
|
161
|
+
const thinkingEndIndex = content.indexOf("\"}");
|
|
162
|
+
const thinkingStartIndex = status === DeepThinkingStatus.Thinking ? content.indexOf("{\"process_msg") : content.indexOf("{\"reasoning_content");
|
|
163
|
+
let jsonStr = null;
|
|
164
|
+
try {
|
|
165
|
+
jsonStr = content.substring(thinkingStartIndex, thinkingEndIndex >= 0 ? thinkingEndIndex : undefined) + "\"}";
|
|
166
|
+
// 转换JSON的时候需要将非法字符过滤掉
|
|
167
|
+
const thinkingObject = JSON.parse(jsonStr.replace(/[\x00-\x1F\x7F]/g, ''));
|
|
168
|
+
// 需要将内容的原文返回
|
|
169
|
+
const originalContent = jsonStr.split('":"')[1];
|
|
170
|
+
// 如果正确的解析JSON,并且当前有包含JSON结束的字符,则把当前思考的JSON内容替换掉
|
|
171
|
+
if (thinkingEndIndex >= 0)
|
|
172
|
+
content = content.substring(thinkingEndIndex + 2);
|
|
173
|
+
// 判断整个思考过程是否结束
|
|
174
|
+
if (status === DeepThinkingStatus.ReasonOutput && thinkingEndIndex >= 0)
|
|
175
|
+
status = DeepThinkingStatus.ThinkingOver;
|
|
176
|
+
// 判断当前是否从前期思考切换到思考内容输出
|
|
177
|
+
if (status === DeepThinkingStatus.Thinking && content.indexOf("{\"reasoning_content") >= 0)
|
|
178
|
+
status = DeepThinkingStatus.ReasonOutput;
|
|
179
|
+
//const removeOutputContent = content.replace(originalContent!.substring(1, originalContent!.length - 2),"")
|
|
180
|
+
let thinkingContent = originalContent === null || originalContent === void 0 ? void 0 : originalContent.substring(0, originalContent.length - 2); //.replace(lastContent, '');
|
|
181
|
+
const outputLength = (thinkingContent === null || thinkingContent === void 0 ? void 0 : thinkingContent.length) || 0;
|
|
182
|
+
const thinkingAction = Object.keys(thinkingObject)[0];
|
|
183
|
+
// 用lastThinkingMessage来记录上一次的思考内容,避免重复输出内容,导致的网络传输内容过多
|
|
184
|
+
if (this.lastThinkingMessage.action === thinkingAction && this.lastThinkingMessage.textposition) {
|
|
185
|
+
thinkingContent = thinkingContent.substring(this.lastThinkingMessage.textposition);
|
|
186
|
+
}
|
|
187
|
+
this.lastThinkingMessage = thinkingEndIndex >= 0 ? { action: thinkingAction, textposition: 0 } : { action: thinkingAction, textposition: outputLength };
|
|
188
|
+
return { successed: true, thinking: {
|
|
189
|
+
action: thinkingAction,
|
|
190
|
+
text: thinkingContent //Object.values(thinkingObject)[0]
|
|
191
|
+
}, content, status };
|
|
192
|
+
}
|
|
193
|
+
catch (error) {
|
|
194
|
+
console.error('解析JSON出错了:' + jsonStr);
|
|
195
|
+
// 当前解析出错,等待下一次解析
|
|
196
|
+
return { successed: false, content, status };
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* 流式传输聊天请求
|
|
201
|
+
* @param chatText
|
|
202
|
+
* @param callChatOption
|
|
203
|
+
* @param attach
|
|
204
|
+
* @param _axiosOption
|
|
205
|
+
* @returns
|
|
206
|
+
*/
|
|
207
|
+
chatRequestInStream(message, callChatOption = {}, attach, _axiosOption) {
|
|
208
|
+
var _a, e_1, _b, _c;
|
|
209
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
210
|
+
if (!message)
|
|
211
|
+
this.emit('chaterror', { successed: false, error: 'no message in chat' });
|
|
212
|
+
///如果是字符,则组装成API需要的消息
|
|
213
|
+
if (typeof message === 'string')
|
|
214
|
+
message = [
|
|
215
|
+
{
|
|
216
|
+
role: api_1.RoleType.User,
|
|
217
|
+
content_type: 'text',
|
|
218
|
+
content: message
|
|
219
|
+
}
|
|
220
|
+
];
|
|
221
|
+
const client = yield this.createClient();
|
|
222
|
+
////如果参数中用的是Workflow,则调用对话流来输出结果
|
|
223
|
+
////否则用智能体的对话来输出结果
|
|
224
|
+
let requestid = Math.ceil(Math.random() * (new Date().getTime() * Math.random()) / 1000), index = 0;
|
|
225
|
+
const params = yield this.getRequestStream(client, message, callChatOption);
|
|
226
|
+
const stream = !callChatOption.workflowid ? client.chat.stream(params) : client.workflows.chat.stream(params);
|
|
227
|
+
let deltaindex = 0, fullanswer = [], followup = [];
|
|
228
|
+
let deepThinking = '', thinkingStatus = DeepThinkingStatus.None; // 是否在深度思考中
|
|
229
|
+
try {
|
|
230
|
+
for (var _d = true, stream_1 = __asyncValues(stream), stream_1_1; stream_1_1 = yield stream_1.next(), _a = stream_1_1.done, !_a;) {
|
|
231
|
+
_c = stream_1_1.value;
|
|
232
|
+
_d = false;
|
|
233
|
+
try {
|
|
234
|
+
const part = _c;
|
|
235
|
+
if (part.event === api_1.ChatEventType.ERROR)
|
|
236
|
+
return this.emit('chaterror', { successed: false, error: 'call failed' });
|
|
237
|
+
if (part.event === api_1.ChatEventType.CONVERSATION_MESSAGE_DELTA) {
|
|
238
|
+
let { conversation_id, content_type, type, role, content } = part.data;
|
|
239
|
+
// 如果存在深度思考,则一开始就会带有相关的关键信息
|
|
240
|
+
if (deltaindex === 0 && content.startsWith("{\"process_msg")) {
|
|
241
|
+
thinkingStatus = DeepThinkingStatus.Thinking;
|
|
242
|
+
deltaindex++;
|
|
243
|
+
}
|
|
244
|
+
// 如果在深度思考中,则不输出消息
|
|
245
|
+
if (thinkingStatus !== DeepThinkingStatus.None &&
|
|
246
|
+
thinkingStatus !== DeepThinkingStatus.ThinkingOver) {
|
|
247
|
+
deepThinking += content;
|
|
248
|
+
const result = this.parseDeepThinkingJson(deepThinking, thinkingStatus);
|
|
249
|
+
if (result.successed) {
|
|
250
|
+
deepThinking = result.content;
|
|
251
|
+
this.emit('chatthinking', result.thinking);
|
|
252
|
+
thinkingStatus = result.status;
|
|
253
|
+
}
|
|
254
|
+
if (thinkingStatus != DeepThinkingStatus.ThinkingOver)
|
|
255
|
+
continue;
|
|
256
|
+
// 将排除了thinking之后的消息内容要带下去成为正式的输出内容
|
|
257
|
+
content = deepThinking;
|
|
258
|
+
}
|
|
259
|
+
fullanswer.push(content);
|
|
260
|
+
let output = { successed: true, type, content_type, role, requestid, segment: content, text: fullanswer.join(''), index: index++, session_id: conversation_id };
|
|
261
|
+
if (attach)
|
|
262
|
+
output = Object.assign({}, output, attach);
|
|
263
|
+
this.emit('chattext', output);
|
|
264
|
+
}
|
|
265
|
+
////在流式传输中,提取相关推荐问题
|
|
266
|
+
if (part.event === api_1.ChatEventType.CONVERSATION_MESSAGE_COMPLETED) {
|
|
267
|
+
const { type, content } = part.data;
|
|
268
|
+
if (type === 'follow_up')
|
|
269
|
+
followup.push(content);
|
|
270
|
+
}
|
|
271
|
+
///整个对话结束
|
|
272
|
+
if (part.event === api_1.ChatEventType.CONVERSATION_CHAT_COMPLETED) {
|
|
273
|
+
const { conversation_id } = part.data;
|
|
274
|
+
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 };
|
|
275
|
+
if (attach)
|
|
276
|
+
output = Object.assign({}, output, attach);
|
|
277
|
+
this.emit('chatdone', output);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
finally {
|
|
281
|
+
_d = true;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
286
|
+
finally {
|
|
287
|
+
try {
|
|
288
|
+
if (!_d && !_a && (_b = stream_1.return)) yield _b.call(stream_1);
|
|
289
|
+
}
|
|
290
|
+
finally { if (e_1) throw e_1.error; }
|
|
291
|
+
}
|
|
292
|
+
return { successed: true, requestid };
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
exports.default = CorzBot;
|
package/dist/deepseek.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const openai_1 = __importDefault(require("openai"));
|
|
7
|
+
const openai_2 = __importDefault(require("./openai"));
|
|
8
|
+
class DeepSeek extends openai_2.default {
|
|
9
|
+
createOpenAI(apiKey) {
|
|
10
|
+
return new openai_1.default({
|
|
11
|
+
baseURL: 'https://api.deepseek.com',
|
|
12
|
+
apiKey
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
exports.default = DeepSeek;
|
package/dist/gptprovider.d.ts
CHANGED
|
@@ -8,8 +8,10 @@ export declare const GptProviderEnum: {
|
|
|
8
8
|
readonly OPENAIPROXY: "openaiproxy";
|
|
9
9
|
readonly MICROSOFT: "microsoft";
|
|
10
10
|
readonly AIMP: "aimp";
|
|
11
|
+
readonly CORZ: "corz";
|
|
11
12
|
readonly BAIDU: "baidu";
|
|
12
13
|
readonly DOUBAO: "doubao";
|
|
14
|
+
readonly DEEPSEEK: "deepseek";
|
|
13
15
|
readonly GOOGLE: "google";
|
|
14
16
|
readonly STABILITY: "stability";
|
|
15
17
|
readonly STABILITY2: "stability2";
|
package/dist/gptprovider.js
CHANGED
|
@@ -9,6 +9,8 @@ exports.createGpt = exports.GptProviderEnum = void 0;
|
|
|
9
9
|
* 语音转文字服务商工厂
|
|
10
10
|
*/
|
|
11
11
|
const openai_1 = __importDefault(require("./openai"));
|
|
12
|
+
const deepseek_1 = __importDefault(require("./deepseek"));
|
|
13
|
+
const corzbot_1 = __importDefault(require("./corzbot"));
|
|
12
14
|
const openaiproxy_1 = __importDefault(require("./openaiproxy"));
|
|
13
15
|
const azureai_1 = __importDefault(require("./azureai"));
|
|
14
16
|
const stabilityai_1 = __importDefault(require("./stabilityai"));
|
|
@@ -16,6 +18,9 @@ const stabilityplusai_1 = __importDefault(require("./stabilityplusai"));
|
|
|
16
18
|
const baiduai_1 = __importDefault(require("./baiduai"));
|
|
17
19
|
const aimp_1 = __importDefault(require("./aimp"));
|
|
18
20
|
const doubaoai_1 = __importDefault(require("./doubaoai"));
|
|
21
|
+
const corzauthorization_1 = require("./corzauthorization");
|
|
22
|
+
// 扣子的身份认证应用
|
|
23
|
+
const corzAuth = new Map();
|
|
19
24
|
/**
|
|
20
25
|
* OpenAI/NLP 的服务提供商 OpenAI,微软,百度文心(待接入),google(待接入)
|
|
21
26
|
*/
|
|
@@ -24,8 +29,10 @@ exports.GptProviderEnum = {
|
|
|
24
29
|
OPENAIPROXY: 'openaiproxy',
|
|
25
30
|
MICROSOFT: 'microsoft',
|
|
26
31
|
AIMP: 'aimp',
|
|
32
|
+
CORZ: 'corz',
|
|
27
33
|
BAIDU: 'baidu',
|
|
28
34
|
DOUBAO: 'doubao',
|
|
35
|
+
DEEPSEEK: 'deepseek',
|
|
29
36
|
GOOGLE: 'google',
|
|
30
37
|
STABILITY: 'stability',
|
|
31
38
|
STABILITY2: 'stability2',
|
|
@@ -42,6 +49,8 @@ function createGpt(provider, apikey, setting) {
|
|
|
42
49
|
switch (provider) {
|
|
43
50
|
case exports.GptProviderEnum.OPENAI:
|
|
44
51
|
return new openai_1.default(apikey + '', { model, maxtoken, temperature, embedding, top_p, presence_penalty, frequency_penalty });
|
|
52
|
+
case exports.GptProviderEnum.DEEPSEEK:
|
|
53
|
+
return new deepseek_1.default(apikey + '', { model, maxtoken, temperature, embedding, top_p, presence_penalty, frequency_penalty });
|
|
45
54
|
case exports.GptProviderEnum.OPENAIPROXY:
|
|
46
55
|
return new openaiproxy_1.default(apikey + '', { serviceurl }, { model, maxtoken, temperature, embedding, top_p, presence_penalty, frequency_penalty });
|
|
47
56
|
case exports.GptProviderEnum.MICROSOFT:
|
|
@@ -51,6 +60,13 @@ function createGpt(provider, apikey, setting) {
|
|
|
51
60
|
return new baiduai_1.default(cred);
|
|
52
61
|
case exports.GptProviderEnum.AIMP:
|
|
53
62
|
return new aimp_1.default(apikey + '', { endpoint, agentid });
|
|
63
|
+
case exports.GptProviderEnum.CORZ:
|
|
64
|
+
let authorizationProvider = corzAuth.get(apikey + '');
|
|
65
|
+
if (!authorizationProvider) {
|
|
66
|
+
authorizationProvider = new corzauthorization_1.CorzAuthorization(apikey + '', setting);
|
|
67
|
+
corzAuth.set(apikey + '', authorizationProvider);
|
|
68
|
+
}
|
|
69
|
+
return new corzbot_1.default(authorizationProvider, setting);
|
|
54
70
|
case exports.GptProviderEnum.DOUBAO:
|
|
55
71
|
return new doubaoai_1.default(apikey + '', { model, maxtoken, temperature, top_p, presence_penalty, frequency_penalty });
|
|
56
72
|
case exports.GptProviderEnum.STABILITY:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "doomiaichat",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.1.4",
|
|
4
4
|
"description": "Doomisoft OpenAI",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"@azure/openai": "^1.0.0-beta.11",
|
|
20
|
-
"
|
|
20
|
+
"@coze/api": "^1.1.0",
|
|
21
|
+
"axios": "^1.8.4",
|
|
21
22
|
"openai": "^4.29.0"
|
|
22
23
|
}
|
|
23
24
|
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { getJWTToken, COZE_CN_BASE_URL } from '@coze/api';
|
|
4
|
+
export class CorzAuthorization {
|
|
5
|
+
private accessToken: string | null |undefined;
|
|
6
|
+
private expiresAt: number = 0;
|
|
7
|
+
private pemfile: string;
|
|
8
|
+
private secret: string;
|
|
9
|
+
private sessionName: string;
|
|
10
|
+
constructor(private appid: string,setting:Record<string,any>) {
|
|
11
|
+
this.secret = setting["keyid"];
|
|
12
|
+
this.pemfile = setting["pemfile"] || "private.pem"
|
|
13
|
+
this.sessionName = setting["sessionName"] || "default";
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* 获取授权令牌
|
|
17
|
+
* @returns
|
|
18
|
+
*/
|
|
19
|
+
async getAccessToken():Promise<string|null> {
|
|
20
|
+
// 检查令牌是否存在且未过期,如果有效直接放回
|
|
21
|
+
if (this.accessToken && Date.now() < this.expiresAt) return this.accessToken;
|
|
22
|
+
// 开始新的授权
|
|
23
|
+
const result = await this.doAuthorize();
|
|
24
|
+
if (!result.successed) return null;
|
|
25
|
+
// 缓存授权令牌和过期时间
|
|
26
|
+
this.accessToken = result.accessToken!;
|
|
27
|
+
// 将 expires_in 转换为绝对时间戳
|
|
28
|
+
this.expiresAt = result.expires_in! * 1000; // 将秒转换为毫秒
|
|
29
|
+
return this.accessToken;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* 进行授权
|
|
33
|
+
* @returns
|
|
34
|
+
*/
|
|
35
|
+
private async doAuthorize(): Promise<{ successed: boolean, accessToken?: string, expires_in?: number,error?:any }> {
|
|
36
|
+
try {
|
|
37
|
+
// 提取您的 COZE API 授权参数
|
|
38
|
+
//const keyid = "H7rAk-5s0TPOs9-rXnCr7pvkPhpJZGArT__UuMyhbkg";
|
|
39
|
+
const aud = "api.coze.cn";
|
|
40
|
+
// 读取私钥
|
|
41
|
+
const fileFullPath =path.join(process.cwd(), this.pemfile);
|
|
42
|
+
if (!fs.existsSync(fileFullPath)) return { successed: false, error: `${fileFullPath} not existed`}
|
|
43
|
+
const privateKey = fs.readFileSync(fileFullPath).toString();
|
|
44
|
+
|
|
45
|
+
// 获取JWT令牌
|
|
46
|
+
const result = await getJWTToken({
|
|
47
|
+
baseURL: COZE_CN_BASE_URL,
|
|
48
|
+
appId:this.appid,
|
|
49
|
+
aud,
|
|
50
|
+
keyid:this.secret,
|
|
51
|
+
privateKey,
|
|
52
|
+
sessionName:this.sessionName,
|
|
53
|
+
});
|
|
54
|
+
return {successed: true, accessToken: result.access_token, expires_in: result.expires_in}
|
|
55
|
+
} catch (error) {
|
|
56
|
+
return { successed: true, error }
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
package/src/corzbot.ts
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 扣子智能体
|
|
3
|
+
*/
|
|
4
|
+
import { CozeAPI,
|
|
5
|
+
COZE_CN_BASE_URL,
|
|
6
|
+
ChatEventType,
|
|
7
|
+
RoleType,
|
|
8
|
+
StreamChatReq,
|
|
9
|
+
EnterMessage,
|
|
10
|
+
ChatWorkflowReq,
|
|
11
|
+
CreateChatReq,
|
|
12
|
+
ChatStatus} from '@coze/api';
|
|
13
|
+
import GptBase from "./gptbase"
|
|
14
|
+
import { CorzAuthorization } from './corzauthorization';
|
|
15
|
+
enum DeepThinkingStatus {
|
|
16
|
+
None,
|
|
17
|
+
Thinking,
|
|
18
|
+
ReasonOutput,
|
|
19
|
+
ThinkingOver
|
|
20
|
+
}
|
|
21
|
+
type TThinkingMessage = { action: string, textposition: number }
|
|
22
|
+
export default class CorzBot extends GptBase {
|
|
23
|
+
protected botid: string;
|
|
24
|
+
private apiKey:string;
|
|
25
|
+
private lastThinkingMessage: TThinkingMessage = { action: '', textposition:0 };
|
|
26
|
+
// protected client: CozeAPI;
|
|
27
|
+
/**
|
|
28
|
+
*
|
|
29
|
+
* @param apikey 调用AI中台 的key
|
|
30
|
+
* @param botid 智能体信息
|
|
31
|
+
*/
|
|
32
|
+
constructor(private authorizationProvider: CorzAuthorization,private setting: any={}) {
|
|
33
|
+
super();
|
|
34
|
+
////初始化扣子客户端
|
|
35
|
+
this.botid = this.setting['botid'];
|
|
36
|
+
this.apiKey = this.setting['apiKey'];
|
|
37
|
+
}
|
|
38
|
+
private async createClient(): Promise<CozeAPI> {
|
|
39
|
+
// 存在AppKey则使用AppKey进行认证
|
|
40
|
+
if (this.apiKey) return new CozeAPI({ baseURL: COZE_CN_BASE_URL, token: this.apiKey });
|
|
41
|
+
const accessToken = await this.authorizationProvider.getAccessToken();
|
|
42
|
+
if (!accessToken) throw new Error('get access token failed');
|
|
43
|
+
return new CozeAPI({ baseURL: COZE_CN_BASE_URL, token: accessToken });
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* 发起一次会话
|
|
47
|
+
*/
|
|
48
|
+
private async createCoversation(client: CozeAPI):Promise<string>{
|
|
49
|
+
const result = await client.conversations.create({
|
|
50
|
+
bot_id: this.botid,
|
|
51
|
+
})
|
|
52
|
+
return result.id;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* 组装请求参数
|
|
56
|
+
* @param message
|
|
57
|
+
* @param callChatOption
|
|
58
|
+
* @param attach
|
|
59
|
+
* @param _axiosOption
|
|
60
|
+
*/
|
|
61
|
+
async getRequestStream<T>(client: CozeAPI, message: EnterMessage[], callChatOption: any = {}): Promise<T> {
|
|
62
|
+
//简单的对话请求
|
|
63
|
+
const conversation_id = callChatOption.session_id ?? await this.createCoversation(client);
|
|
64
|
+
if (!callChatOption.workflowid) {
|
|
65
|
+
const req: StreamChatReq = {
|
|
66
|
+
bot_id: this.botid,
|
|
67
|
+
additional_messages: message,
|
|
68
|
+
user_id: callChatOption.userid || callChatOption.cozeUserID,
|
|
69
|
+
conversation_id
|
|
70
|
+
}
|
|
71
|
+
req.custom_variables = Object.assign({}, this.setting.customVariables || {}, callChatOption.customVariables || {});
|
|
72
|
+
return req as T;
|
|
73
|
+
}
|
|
74
|
+
const worflowreq: ChatWorkflowReq = {
|
|
75
|
+
bot_id: this.botid,
|
|
76
|
+
additional_messages: message,
|
|
77
|
+
workflow_id: callChatOption.workflowid,
|
|
78
|
+
conversation_id,
|
|
79
|
+
parameters: Object.assign({}, this.setting.customVariables || {}, callChatOption.customVariables || {}),
|
|
80
|
+
}
|
|
81
|
+
return worflowreq as T;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* 非流式传输聊天请求
|
|
85
|
+
* @param chatText
|
|
86
|
+
* @param callChatOption
|
|
87
|
+
* @param _axiosOption
|
|
88
|
+
*/
|
|
89
|
+
public async chatRequest(message: any[]|string, callChatOption: any={}, _axiosOption: any = {}): Promise<any> {
|
|
90
|
+
if (!message) this.emit('chaterror', { successed: false, error: 'no message in chat' });
|
|
91
|
+
///如果是字符,则组装成API需要的消息
|
|
92
|
+
if (typeof message === 'string') message = [
|
|
93
|
+
{
|
|
94
|
+
role: RoleType.User,
|
|
95
|
+
content_type:'text' ,
|
|
96
|
+
content: message
|
|
97
|
+
}
|
|
98
|
+
];
|
|
99
|
+
const client = await this.createClient();
|
|
100
|
+
////如果参数中用的是Workflow,则调用对话流来输出结果
|
|
101
|
+
////否则用智能体的对话来输出结果
|
|
102
|
+
const params =await this.getRequestStream(client, message, callChatOption);
|
|
103
|
+
const response = await client.chat.createAndPoll(params as CreateChatReq);
|
|
104
|
+
if (response.chat.status === ChatStatus.COMPLETED && response.messages) {
|
|
105
|
+
const message = response.messages.filter(x=>x.type==='answer').map(item => ({
|
|
106
|
+
role: item.role,
|
|
107
|
+
type: item.type,
|
|
108
|
+
content: item.content,
|
|
109
|
+
}));
|
|
110
|
+
const follow_up = response.messages.filter(x => x.type === 'follow_up').map(item => ({
|
|
111
|
+
role: item.role,
|
|
112
|
+
type: item.type,
|
|
113
|
+
content: item.content,
|
|
114
|
+
}));
|
|
115
|
+
return { successed: true, message, follow_up,usage: response.chat.usage };
|
|
116
|
+
}
|
|
117
|
+
return { successed: false, error: { message: '聊天未完成', status: response.chat.status } };
|
|
118
|
+
// for await (const part of stream) {
|
|
119
|
+
// if (part.event === ChatEventType.ERROR) return { successed: false, error: part.data.msg }
|
|
120
|
+
// ////在流式传输中,提取相关推荐问题
|
|
121
|
+
// if (part.event === ChatEventType.CONVERSATION_MESSAGE_COMPLETED) {
|
|
122
|
+
// const { type, content, conversation_id } = part.data;
|
|
123
|
+
// ///回答全部结束
|
|
124
|
+
// if (type === 'answer') return { successed: true, message: [{ message: { content } }], session_id: conversation_id };
|
|
125
|
+
// }
|
|
126
|
+
// }
|
|
127
|
+
//return { successed: false, error:'unknow' }
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* 解析深度思考的JSON内容
|
|
131
|
+
* @param content
|
|
132
|
+
* @param status
|
|
133
|
+
* @returns
|
|
134
|
+
*/
|
|
135
|
+
private parseDeepThinkingJson(content: string,status: DeepThinkingStatus) {
|
|
136
|
+
const thinkingEndIndex = content.indexOf("\"}");
|
|
137
|
+
const thinkingStartIndex = status === DeepThinkingStatus.Thinking ? content.indexOf("{\"process_msg") : content.indexOf("{\"reasoning_content");
|
|
138
|
+
let jsonStr = null;
|
|
139
|
+
try{
|
|
140
|
+
jsonStr = content.substring(thinkingStartIndex, thinkingEndIndex >= 0 ? thinkingEndIndex : undefined) +"\"}";
|
|
141
|
+
// 转换JSON的时候需要将非法字符过滤掉
|
|
142
|
+
const thinkingObject = JSON.parse(jsonStr.replace(/[\x00-\x1F\x7F]/g, ''));
|
|
143
|
+
// 需要将内容的原文返回
|
|
144
|
+
const originalContent = jsonStr.split('":"')[1];
|
|
145
|
+
// 如果正确的解析JSON,并且当前有包含JSON结束的字符,则把当前思考的JSON内容替换掉
|
|
146
|
+
if (thinkingEndIndex >= 0) content = content.substring(thinkingEndIndex+2);
|
|
147
|
+
// 判断整个思考过程是否结束
|
|
148
|
+
if (status === DeepThinkingStatus.ReasonOutput && thinkingEndIndex >= 0) status = DeepThinkingStatus.ThinkingOver;
|
|
149
|
+
// 判断当前是否从前期思考切换到思考内容输出
|
|
150
|
+
if (status === DeepThinkingStatus.Thinking && content.indexOf("{\"reasoning_content") >= 0) status=DeepThinkingStatus.ReasonOutput;
|
|
151
|
+
//const removeOutputContent = content.replace(originalContent!.substring(1, originalContent!.length - 2),"")
|
|
152
|
+
let thinkingContent = originalContent?.substring(0, originalContent.length - 2)//.replace(lastContent, '');
|
|
153
|
+
const outputLength = thinkingContent?.length || 0;
|
|
154
|
+
const thinkingAction = Object.keys(thinkingObject)[0];
|
|
155
|
+
// 用lastThinkingMessage来记录上一次的思考内容,避免重复输出内容,导致的网络传输内容过多
|
|
156
|
+
if (this.lastThinkingMessage.action === thinkingAction && this.lastThinkingMessage.textposition){
|
|
157
|
+
thinkingContent = thinkingContent!.substring(this.lastThinkingMessage.textposition)
|
|
158
|
+
}
|
|
159
|
+
this.lastThinkingMessage = thinkingEndIndex >= 0 ? { action: thinkingAction!, textposition:0 } : { action: thinkingAction!, textposition: outputLength }
|
|
160
|
+
|
|
161
|
+
return { successed: true,thinking:{
|
|
162
|
+
action: thinkingAction,
|
|
163
|
+
text: thinkingContent//Object.values(thinkingObject)[0]
|
|
164
|
+
}, content, status}
|
|
165
|
+
}
|
|
166
|
+
catch(error){
|
|
167
|
+
console.error('解析JSON出错了:' + jsonStr)
|
|
168
|
+
// 当前解析出错,等待下一次解析
|
|
169
|
+
return { successed: false, content, status }
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* 流式传输聊天请求
|
|
174
|
+
* @param chatText
|
|
175
|
+
* @param callChatOption
|
|
176
|
+
* @param attach
|
|
177
|
+
* @param _axiosOption
|
|
178
|
+
* @returns
|
|
179
|
+
*/
|
|
180
|
+
override async chatRequestInStream(message: any[]|string, callChatOption: any={}, attach?: any, _axiosOption?: any): Promise<any> {
|
|
181
|
+
if (!message) this.emit('chaterror', { successed: false, error: 'no message in chat' });
|
|
182
|
+
///如果是字符,则组装成API需要的消息
|
|
183
|
+
if (typeof message === 'string') message = [
|
|
184
|
+
{
|
|
185
|
+
role: RoleType.User,
|
|
186
|
+
content_type: 'text',
|
|
187
|
+
content: message
|
|
188
|
+
}
|
|
189
|
+
];
|
|
190
|
+
const client = await this.createClient();
|
|
191
|
+
////如果参数中用的是Workflow,则调用对话流来输出结果
|
|
192
|
+
////否则用智能体的对话来输出结果
|
|
193
|
+
let requestid = Math.ceil(Math.random() * (new Date().getTime() * Math.random()) / 1000), index=0;
|
|
194
|
+
const params =await this.getRequestStream(client, message, callChatOption);
|
|
195
|
+
const stream = !callChatOption.workflowid? client.chat.stream(params as StreamChatReq) : client.workflows.chat.stream(params as ChatWorkflowReq);
|
|
196
|
+
let deltaindex = 0, fullanswer: string[] = [], followup: string[] = [];
|
|
197
|
+
let deepThinking = '', thinkingStatus = DeepThinkingStatus.None; // 是否在深度思考中
|
|
198
|
+
for await (const part of stream) {
|
|
199
|
+
if (part.event === ChatEventType.ERROR) return this.emit('chaterror', { successed: false, error: 'call failed' });
|
|
200
|
+
if (part.event === ChatEventType.CONVERSATION_MESSAGE_DELTA) {
|
|
201
|
+
let { conversation_id, content_type,type, role, content } = part.data;
|
|
202
|
+
// 如果存在深度思考,则一开始就会带有相关的关键信息
|
|
203
|
+
if (deltaindex === 0 && content.startsWith("{\"process_msg")) {
|
|
204
|
+
thinkingStatus=DeepThinkingStatus.Thinking;
|
|
205
|
+
deltaindex++;
|
|
206
|
+
}
|
|
207
|
+
// 如果在深度思考中,则不输出消息
|
|
208
|
+
if (thinkingStatus !== DeepThinkingStatus.None &&
|
|
209
|
+
thinkingStatus !== DeepThinkingStatus.ThinkingOver
|
|
210
|
+
){
|
|
211
|
+
deepThinking += content;
|
|
212
|
+
const result = this.parseDeepThinkingJson(deepThinking, thinkingStatus)
|
|
213
|
+
if (result.successed){
|
|
214
|
+
deepThinking = result.content;
|
|
215
|
+
this.emit('chatthinking', result.thinking);
|
|
216
|
+
thinkingStatus = result.status;
|
|
217
|
+
}
|
|
218
|
+
if (thinkingStatus != DeepThinkingStatus.ThinkingOver) continue;
|
|
219
|
+
// 将排除了thinking之后的消息内容要带下去成为正式的输出内容
|
|
220
|
+
content = deepThinking;
|
|
221
|
+
}
|
|
222
|
+
fullanswer.push(content);
|
|
223
|
+
let output = { successed: true, type, content_type, role, requestid, segment: content, text: fullanswer.join(''), index: index++, session_id: conversation_id };
|
|
224
|
+
if (attach) output = Object.assign({}, output, attach);
|
|
225
|
+
this.emit('chattext', output)
|
|
226
|
+
}
|
|
227
|
+
////在流式传输中,提取相关推荐问题
|
|
228
|
+
if (part.event === ChatEventType.CONVERSATION_MESSAGE_COMPLETED) {
|
|
229
|
+
const { type, content} = part.data;
|
|
230
|
+
if (type ==='follow_up') followup.push(content);
|
|
231
|
+
}
|
|
232
|
+
///整个对话结束
|
|
233
|
+
if (part.event === ChatEventType.CONVERSATION_CHAT_COMPLETED) {
|
|
234
|
+
const { conversation_id} = part.data;
|
|
235
|
+
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 };
|
|
236
|
+
if (attach) output = Object.assign({}, output, attach);
|
|
237
|
+
this.emit('chatdone', output)
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return { successed: true, requestid }
|
|
241
|
+
}
|
|
242
|
+
}
|
package/src/deepseek.ts
ADDED
package/src/gptprovider.ts
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
* 语音转文字服务商工厂
|
|
4
4
|
*/
|
|
5
5
|
import OpenAIGpt from './openai';
|
|
6
|
+
import DeepSeek from './deepseek';
|
|
7
|
+
import CorzBot from './corzbot'
|
|
6
8
|
import OpenAIProxt from './openaiproxy';
|
|
7
9
|
import AzureAI from './azureai'
|
|
8
10
|
import StabilityAI from './stabilityai'
|
|
@@ -11,6 +13,9 @@ import BaiduWenXinAI, { ApiCredential } from './baiduai'
|
|
|
11
13
|
import AIMiddlePlatform from './aimp';
|
|
12
14
|
import DouBaoAI from './doubaoai'
|
|
13
15
|
import GptBase from './gptbase';
|
|
16
|
+
import { CorzAuthorization } from './corzauthorization'
|
|
17
|
+
// 扣子的身份认证应用
|
|
18
|
+
const corzAuth: Map<string, CorzAuthorization> = new Map();
|
|
14
19
|
/**
|
|
15
20
|
* OpenAI/NLP 的服务提供商 OpenAI,微软,百度文心(待接入),google(待接入)
|
|
16
21
|
*/
|
|
@@ -19,8 +24,10 @@ export const GptProviderEnum = {
|
|
|
19
24
|
OPENAIPROXY:'openaiproxy',
|
|
20
25
|
MICROSOFT: 'microsoft',
|
|
21
26
|
AIMP: 'aimp', ///AI 中台业务
|
|
27
|
+
CORZ:'corz',
|
|
22
28
|
BAIDU: 'baidu',
|
|
23
29
|
DOUBAO:'doubao',
|
|
30
|
+
DEEPSEEK:'deepseek',
|
|
24
31
|
GOOGLE:'google',
|
|
25
32
|
STABILITY:'stability',
|
|
26
33
|
STABILITY2: 'stability2',
|
|
@@ -38,6 +45,8 @@ export function createGpt(provider: GptProviderEnum, apikey: string|ApiCredentia
|
|
|
38
45
|
switch (provider) {
|
|
39
46
|
case GptProviderEnum.OPENAI:
|
|
40
47
|
return new OpenAIGpt(apikey + '', { model, maxtoken, temperature, embedding, top_p, presence_penalty, frequency_penalty });
|
|
48
|
+
case GptProviderEnum.DEEPSEEK:
|
|
49
|
+
return new DeepSeek(apikey + '', { model, maxtoken, temperature, embedding, top_p, presence_penalty, frequency_penalty });
|
|
41
50
|
case GptProviderEnum.OPENAIPROXY:
|
|
42
51
|
return new OpenAIProxt(apikey + '', { serviceurl}, { model, maxtoken, temperature, embedding, top_p, presence_penalty, frequency_penalty });
|
|
43
52
|
case GptProviderEnum.MICROSOFT:
|
|
@@ -47,6 +56,13 @@ export function createGpt(provider: GptProviderEnum, apikey: string|ApiCredentia
|
|
|
47
56
|
return new BaiduWenXinAI(cred);
|
|
48
57
|
case GptProviderEnum.AIMP:
|
|
49
58
|
return new AIMiddlePlatform(apikey+'',{ endpoint,agentid });
|
|
59
|
+
case GptProviderEnum.CORZ:
|
|
60
|
+
let authorizationProvider = corzAuth.get(apikey + '');
|
|
61
|
+
if (!authorizationProvider) {
|
|
62
|
+
authorizationProvider = new CorzAuthorization(apikey + '',setting);
|
|
63
|
+
corzAuth.set(apikey + '', authorizationProvider);
|
|
64
|
+
}
|
|
65
|
+
return new CorzBot(authorizationProvider!, setting);
|
|
50
66
|
case GptProviderEnum.DOUBAO:
|
|
51
67
|
return new DouBaoAI(apikey + '', { model, maxtoken, temperature, top_p, presence_penalty, frequency_penalty })
|
|
52
68
|
case GptProviderEnum.STABILITY:
|