doomiaichat 7.1.29 → 7.1.31
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/index.esm.js +16 -0
- package/dist/index.js +16 -28
- package/dist/{aimp.d.ts → types/aimp.d.ts} +1 -0
- package/dist/types/aimp.d.ts.map +1 -0
- package/dist/{azureai.d.ts → types/azureai.d.ts} +1 -0
- package/dist/types/azureai.d.ts.map +1 -0
- package/dist/{corzauthorization.d.ts → types/corzauthorization.d.ts} +1 -0
- package/dist/types/corzauthorization.d.ts.map +1 -0
- package/dist/{corzbot.d.ts → types/corzbot.d.ts} +1 -0
- package/dist/types/corzbot.d.ts.map +1 -0
- package/dist/{declare.d.ts → types/declare.d.ts} +2 -1
- package/dist/types/declare.d.ts.map +1 -0
- package/dist/{doubaoai.d.ts → types/doubaoai.d.ts} +1 -0
- package/dist/types/doubaoai.d.ts.map +1 -0
- package/dist/{gptbase.d.ts → types/gptbase.d.ts} +1 -1
- package/dist/types/gptbase.d.ts.map +1 -0
- package/dist/{gptprovider.d.ts → types/gptprovider.d.ts} +2 -7
- package/dist/types/gptprovider.d.ts.map +1 -0
- package/dist/{index.d.ts → types/index.d.ts} +1 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/{openai.d.ts → types/openai.d.ts} +1 -0
- package/dist/types/openai.d.ts.map +1 -0
- package/dist/{openaibase.d.ts → types/openaibase.d.ts} +1 -0
- package/dist/types/openaibase.d.ts.map +1 -0
- package/dist/{openaiproxy.d.ts → types/openaiproxy.d.ts} +1 -0
- package/dist/types/openaiproxy.d.ts.map +1 -0
- package/package.json +16 -4
- package/dist/aimp.js +0 -162
- package/dist/azureai.js +0 -220
- package/dist/baiduai.d.ts +0 -28
- package/dist/baiduai.js +0 -92
- package/dist/corzauthorization.js +0 -79
- package/dist/corzbot.js +0 -490
- package/dist/declare.js +0 -51
- package/dist/deepseek.d.ts +0 -5
- package/dist/deepseek.js +0 -16
- package/dist/doubaoai.js +0 -149
- package/dist/gptbase.js +0 -58
- package/dist/gptprovider.js +0 -80
- package/dist/openai.js +0 -184
- package/dist/openaibase.js +0 -20
- package/dist/openaiprovider.d.ts +0 -20
- package/dist/openaiprovider.js +0 -43
- package/dist/openaiproxy.js +0 -108
- package/dist/stabilityai.d.ts +0 -18
- package/dist/stabilityai.js +0 -75
- package/dist/stabilityplusai.d.ts +0 -11
- package/dist/stabilityplusai.js +0 -86
- package/src/aimp.ts +0 -125
- package/src/azureai.ts +0 -180
- package/src/baiduai.ts +0 -86
- package/src/corzauthorization.ts +0 -59
- package/src/corzbot.ts +0 -434
- package/src/declare.ts +0 -152
- package/src/deepseek.ts +0 -11
- package/src/doubaoai.ts +0 -129
- package/src/gptbase.ts +0 -52
- package/src/gptprovider.ts +0 -74
- package/src/index.ts +0 -2
- package/src/openai.ts +0 -136
- package/src/openaibase.ts +0 -30
- package/src/openaiproxy.ts +0 -97
- package/src/stabilityai.ts +0 -67
- package/src/stabilityplusai.ts +0 -77
- package/tsconfig.json +0 -31
package/src/baiduai.ts
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import { ApiResult, CacheProvider, request } from "./declare";
|
|
2
|
-
import GptBase from "./gptbase"
|
|
3
|
-
const TOKEN_CACHE_KEY = "key:_doomisoft:baiduwenxin:"
|
|
4
|
-
export default class BaiduWenXinAI extends GptBase {
|
|
5
|
-
|
|
6
|
-
protected credential: ApiCredential;
|
|
7
|
-
private Cacher: CacheProvider|undefined;
|
|
8
|
-
/**
|
|
9
|
-
*
|
|
10
|
-
* @param credential 调用OpenAI 的key
|
|
11
|
-
* @param cacher 用作accesstoken的缓存
|
|
12
|
-
* @param apiOption 用作accesstoken的缓存
|
|
13
|
-
*/
|
|
14
|
-
constructor(credential: ApiCredential, cacher?:CacheProvider) {
|
|
15
|
-
super();
|
|
16
|
-
this.credential = credential;
|
|
17
|
-
this.Cacher = cacher;
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* 获取调用Api的Token
|
|
21
|
-
*/
|
|
22
|
-
async getAccessToken():Promise<AccessTokenResult>{
|
|
23
|
-
////如果当前应用是一个委托到第三方的
|
|
24
|
-
///公众号或小程序,则需要用关联的第三方平台来获取api调用的accesstoken
|
|
25
|
-
////如果是需要缓存token,则首先看缓存中是否有AccessToken
|
|
26
|
-
const accesstoken = this.Cacher ? (await this.Cacher.get(TOKEN_CACHE_KEY+this.credential.apikey)):null;
|
|
27
|
-
if (accesstoken) return { successed: true, access_token: accesstoken };
|
|
28
|
-
const option = {
|
|
29
|
-
url: `https://wenxin.baidu.com/moduleApi/portal/api/oauth/token?grant_type=client_credentials&client_id=${this.credential.apikey}&client_secret=${this.credential.securitykey}`,
|
|
30
|
-
method:"post",
|
|
31
|
-
};
|
|
32
|
-
const tokenData = await request(option);
|
|
33
|
-
if (tokenData.successed == true && !tokenData.data.code) {
|
|
34
|
-
///把api accesstoken缓存起来
|
|
35
|
-
if (this.Cacher){
|
|
36
|
-
this.Cacher.set(TOKEN_CACHE_KEY + this.credential.apikey, tokenData.data.data,3600*20);
|
|
37
|
-
}
|
|
38
|
-
return { successed: true, access_token: tokenData.data.data };
|
|
39
|
-
}
|
|
40
|
-
return { successed: false, error: tokenData.data.msg }
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* 请求GPT接口
|
|
45
|
-
*/
|
|
46
|
-
public async chatRequest(chatText: string | Array<any>, _paramOption: any, axiosOption: any = {}): Promise<ApiResult> {
|
|
47
|
-
console.log('call baidu')
|
|
48
|
-
if (!chatText) return { successed: false, error: { errcode: 2, errmsg: '缺失聊天的内容' } };
|
|
49
|
-
const accessToken = await this.getAccessToken();
|
|
50
|
-
if (!accessToken.successed || !accessToken.access_token) return {successed:false,error:'accesstoken get failed'}
|
|
51
|
-
try {
|
|
52
|
-
let param = {
|
|
53
|
-
...axiosOption,
|
|
54
|
-
method: "post",
|
|
55
|
-
data: {
|
|
56
|
-
text: `问题:${chatText}\n回答:`,
|
|
57
|
-
seq_len: 512,
|
|
58
|
-
topp: 0.5,
|
|
59
|
-
penalty_score: 1.2,
|
|
60
|
-
min_dec_len: 12,
|
|
61
|
-
min_dec_penalty_text: "。?:![<S>]",
|
|
62
|
-
task_prompt: "qa",
|
|
63
|
-
mask_type: "paragraph"
|
|
64
|
-
},
|
|
65
|
-
url:`https://wenxin.baidu.com/moduleApi/portal/api/rest/1.0/ernie/3.0.25/zeus?access_token=${accessToken.access_token}`
|
|
66
|
-
};
|
|
67
|
-
console.log('param', param)
|
|
68
|
-
const response = await request(param)
|
|
69
|
-
if (response.successed && !response.data.code) {
|
|
70
|
-
return { successed: true, ...response.data };
|
|
71
|
-
}
|
|
72
|
-
return { successed: false, ...response.data };
|
|
73
|
-
} catch (error) {
|
|
74
|
-
console.log('result is error ', error)
|
|
75
|
-
return { successed: false, error };
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
export interface AccessTokenResult extends ApiResult {
|
|
81
|
-
'access_token'?: string
|
|
82
|
-
}
|
|
83
|
-
export interface ApiCredential{
|
|
84
|
-
'apikey':string,
|
|
85
|
-
'securitykey': string
|
|
86
|
-
}
|
package/src/corzauthorization.ts
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
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(public 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
DELETED
|
@@ -1,434 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 扣子智能体
|
|
3
|
-
*/
|
|
4
|
-
import {
|
|
5
|
-
CozeAPI,
|
|
6
|
-
COZE_CN_BASE_URL,
|
|
7
|
-
ChatEventType,
|
|
8
|
-
RoleType,
|
|
9
|
-
StreamChatReq,
|
|
10
|
-
EnterMessage,
|
|
11
|
-
// ChatWorkflowReq,
|
|
12
|
-
// CreateChatReq,
|
|
13
|
-
// ChatStatus,
|
|
14
|
-
VariableUpdateReq,
|
|
15
|
-
VariableRetrieveReq,
|
|
16
|
-
CreateChatReq,
|
|
17
|
-
RunWorkflowReq,
|
|
18
|
-
RunWorkflowData,
|
|
19
|
-
CreateChatData,
|
|
20
|
-
ChatStatus,
|
|
21
|
-
WorkflowEventType,
|
|
22
|
-
ChatWorkflowReq
|
|
23
|
-
} from '@coze/api';
|
|
24
|
-
import GptBase from "./gptbase"
|
|
25
|
-
import { CorzAuthorization } from './corzauthorization';
|
|
26
|
-
import { parse } from 'querystring'
|
|
27
|
-
import { ApiResult } from './declare';
|
|
28
|
-
import {createWriteStream,mkdirSync} from 'fs';
|
|
29
|
-
import {resolve,join} from 'path';
|
|
30
|
-
// 定义深度思考的动作标签
|
|
31
|
-
// 这是小鹭里面专用的几个思考动作标签
|
|
32
|
-
const DeepThinkingAction: any = {
|
|
33
|
-
thinking: { start: '<xiaolu-think>', end: '</xiaolu-think>', tag: 'xiaolu-think' },
|
|
34
|
-
reasoning: { start: '<xiaolu-reason>', end: '</xiaolu-reason>', tag: 'xiaolu-reason' },
|
|
35
|
-
card: { start: '<xiaolu-card>', end: '</xiaolu-card>', tag: 'xiaolu-card' },
|
|
36
|
-
preresponse: { start: '<xiaolu-preresponse>', end: '</xiaolu-preresponse>', tag: 'xiaolu-preresponse' },
|
|
37
|
-
}
|
|
38
|
-
// 定义深度思考的状态
|
|
39
|
-
enum DeepThinkingStatus {
|
|
40
|
-
None,
|
|
41
|
-
Thinking,
|
|
42
|
-
// ContentOutput,
|
|
43
|
-
ThinkingOver
|
|
44
|
-
}
|
|
45
|
-
// 智能体思考时输出的动作
|
|
46
|
-
type CardType = { type: number, tag: string }
|
|
47
|
-
// type TThinkingMessage = { action: string, textposition: number }
|
|
48
|
-
export default class CorzBot extends GptBase {
|
|
49
|
-
private botid: string | null = null; // 智能体id
|
|
50
|
-
private workflowid: string | null = null; // 工作流id
|
|
51
|
-
private talkflowid: string | null = null; // 对话流id
|
|
52
|
-
private apiKey: string;
|
|
53
|
-
private debugDir: string = '';
|
|
54
|
-
private debug: boolean = false;
|
|
55
|
-
/**
|
|
56
|
-
*
|
|
57
|
-
* @param apikey 调用AI中台 的key
|
|
58
|
-
* @param botid 智能体信息
|
|
59
|
-
*/
|
|
60
|
-
constructor(private authorizationProvider: CorzAuthorization, private setting: any = {}) {
|
|
61
|
-
super();
|
|
62
|
-
////初始化扣子客户端
|
|
63
|
-
|
|
64
|
-
if (this.setting.workflowid)
|
|
65
|
-
this.workflowid = this.setting.workflowid;
|
|
66
|
-
else if (this.setting.talkflowid)
|
|
67
|
-
this.talkflowid = this.setting.talkflowid;
|
|
68
|
-
else if (this.setting.botid || this.setting.botID)
|
|
69
|
-
this.botid = this.setting.botid || this.setting.botID;
|
|
70
|
-
else
|
|
71
|
-
throw new Error('no botid or talkflowid or workflowid setting for coze');
|
|
72
|
-
/// 如果开启debug模式,则创建记录日志的目录,将日志输出到该目录
|
|
73
|
-
if (setting.debug === true) {
|
|
74
|
-
this.debug = true;
|
|
75
|
-
this.debugDir = join(setting.logPath || resolve(process.cwd(), './cozedebug'),this.setting.model || 'chat');
|
|
76
|
-
mkdirSync(this.debugDir!, { recursive: true });
|
|
77
|
-
}
|
|
78
|
-
this.apiKey = this.setting['apiKey'];
|
|
79
|
-
}
|
|
80
|
-
private async createClient(): Promise<CozeAPI> {
|
|
81
|
-
// 存在AppKey则使用AppKey进行认证
|
|
82
|
-
if (this.apiKey) return new CozeAPI({ baseURL: COZE_CN_BASE_URL, token: this.apiKey });
|
|
83
|
-
const accessToken = await this.authorizationProvider.getAccessToken();
|
|
84
|
-
if (!accessToken) throw new Error('get access token failed');
|
|
85
|
-
return new CozeAPI({ baseURL: COZE_CN_BASE_URL, token: accessToken });
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* 发起一次会话
|
|
89
|
-
*/
|
|
90
|
-
override async createCoversation(client?: CozeAPI): Promise<string | null> {
|
|
91
|
-
try {
|
|
92
|
-
const czApi = client ?? await this.createClient();
|
|
93
|
-
const params = this.botid ? { bot_id: this.botid } : {};
|
|
94
|
-
const result = await czApi.conversations.create(params)
|
|
95
|
-
return result.id;
|
|
96
|
-
} catch (error) {
|
|
97
|
-
console.error('createCoversation error in coze api');
|
|
98
|
-
return null;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* 设置Coze的变量
|
|
103
|
-
* @param params
|
|
104
|
-
* @returns
|
|
105
|
-
*/
|
|
106
|
-
override async setVariables(params: any = {}): Promise<ApiResult> {
|
|
107
|
-
const client = await this.createClient();
|
|
108
|
-
!params.type && (params.type='app');
|
|
109
|
-
const cozeParams: VariableUpdateReq = { data: params.data };
|
|
110
|
-
params.type === 'app' && (cozeParams.app_id = this.authorizationProvider.appid);
|
|
111
|
-
params.type === 'bot' && this.botid && (cozeParams.bot_id = this.botid);
|
|
112
|
-
params.user_id && (cozeParams.connector_uid = params.user_id);
|
|
113
|
-
//Object.assign({ connector_uid: params?.user_id||'123456' }, params.type==='app'?{app_id:this.authorizationProvider.appid}:(params.type==='bot' ? { bot_id: this.botid } : {}), params);
|
|
114
|
-
const result = await client.variables.update(cozeParams, { debug : true })
|
|
115
|
-
console.log('setVariables result', result);
|
|
116
|
-
return { successed: true };
|
|
117
|
-
}
|
|
118
|
-
/**
|
|
119
|
-
* 获取设置的变量
|
|
120
|
-
* @returns
|
|
121
|
-
*/
|
|
122
|
-
override async getVariables(params: any): Promise<any> {
|
|
123
|
-
const client = await this.createClient();
|
|
124
|
-
const cozeParams: VariableRetrieveReq = Object.assign({}, { bot_id: this.botid }, params);
|
|
125
|
-
const data = await client.variables.retrieve(cozeParams);
|
|
126
|
-
if (data) return { successed: true, ...data }
|
|
127
|
-
return { successed: false, error: 'get variables failed' };
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* 组装请求参数
|
|
131
|
-
* @param message
|
|
132
|
-
* @param callChatOption
|
|
133
|
-
* @param attach
|
|
134
|
-
* @param _axiosOption
|
|
135
|
-
*/
|
|
136
|
-
async getRequestStream<T>(client: CozeAPI, message: EnterMessage[], callChatOption: any = {}): Promise<T> {
|
|
137
|
-
//简单的对话请求
|
|
138
|
-
if (this.botid) {
|
|
139
|
-
const req: StreamChatReq = {
|
|
140
|
-
bot_id: this.botid,
|
|
141
|
-
additional_messages: message,
|
|
142
|
-
user_id: callChatOption.userid || callChatOption.cozeUserID,
|
|
143
|
-
conversation_id: callChatOption.session_id ?? await this.createCoversation(client),
|
|
144
|
-
parameters: Object.assign({ request_src: 1 }, callChatOption.parameters || {}),
|
|
145
|
-
}
|
|
146
|
-
req.custom_variables = Object.assign({}, this.setting.customVariables || {}, callChatOption.customVariables || {});
|
|
147
|
-
return req as T;
|
|
148
|
-
}
|
|
149
|
-
if (this.workflowid) {
|
|
150
|
-
const worflowreq: RunWorkflowReq = {
|
|
151
|
-
ext: callChatOption.ext,
|
|
152
|
-
workflow_id: this.workflowid,//callChatOption.workflowid,
|
|
153
|
-
is_async: false,
|
|
154
|
-
// parameters: Object.assign({ input: message[0]?.content }, this.setting.customVariables || {}, callChatOption.customVariables || {}),
|
|
155
|
-
// parameters: Object.assign({ request_src: 1 }, callChatOption.parameters || {}, { input: message[0]?.content })
|
|
156
|
-
parameters: Object.assign({ request_src: 1 }, callChatOption.parameters || {}, { input: message})
|
|
157
|
-
}
|
|
158
|
-
if (callChatOption.userid || callChatOption.cozeUserID) worflowreq.ext = Object.assign({}, worflowreq.ext || {}, { user_id: callChatOption.userid || callChatOption.cozeUserID });
|
|
159
|
-
return worflowreq as T;
|
|
160
|
-
}
|
|
161
|
-
const worflowreq: ChatWorkflowReq = {
|
|
162
|
-
additional_messages: message,
|
|
163
|
-
ext: {user_id:'12345678'},
|
|
164
|
-
workflow_id: this.talkflowid!,//callChatOption.workflowid,
|
|
165
|
-
conversation_id: callChatOption.session_id ?? await this.createCoversation(client),
|
|
166
|
-
parameters: Object.assign({ request_src: 1 }, callChatOption.parameters || {}) //Object.assign({}, this.setting.customVariables || {}, callChatOption.customVariables || {}),
|
|
167
|
-
}
|
|
168
|
-
if (callChatOption.userid || callChatOption.cozeUserID) worflowreq.ext = Object.assign({}, worflowreq.ext||{}, { user_id: callChatOption.userid || callChatOption.cozeUserID });
|
|
169
|
-
return worflowreq as T;
|
|
170
|
-
}
|
|
171
|
-
/**
|
|
172
|
-
* 同步调用的问答请求需要获取会话详情
|
|
173
|
-
* @param chatid
|
|
174
|
-
* @param conversation_id
|
|
175
|
-
*/
|
|
176
|
-
private async getChatDetail(client: CozeAPI, conversation_id: string, chatid: string) {
|
|
177
|
-
const maxWaitTime = 120000; // 最大等待120秒
|
|
178
|
-
const startTime = Date.now();
|
|
179
|
-
while ((Date.now() - startTime) < maxWaitTime) {
|
|
180
|
-
const chatinfo = await client.chat.retrieve(conversation_id, chatid);
|
|
181
|
-
// 状态已经是完成了,可以去获取对话的内容了
|
|
182
|
-
if (chatinfo.status === ChatStatus.COMPLETED) return { usage: chatinfo.usage, messages: await client.chat.messages.list(conversation_id, chatid) };
|
|
183
|
-
await new Promise(resolve => setTimeout(resolve, 1500)); // 等待1500ms
|
|
184
|
-
}
|
|
185
|
-
return null;
|
|
186
|
-
}
|
|
187
|
-
/**
|
|
188
|
-
* 非流式传输聊天请求
|
|
189
|
-
* @param chatText
|
|
190
|
-
* @param callChatOption
|
|
191
|
-
* @param _axiosOption
|
|
192
|
-
*/
|
|
193
|
-
public async chatRequest(message: any[] | string, callChatOption: any = {}, _axiosOption: any = {}): Promise<any> {
|
|
194
|
-
if (!message) this.emit('chaterror', { successed: false, error: 'no message in chat' });
|
|
195
|
-
///如果是字符,则组装成API需要的消息
|
|
196
|
-
if (typeof message === 'string') message = [
|
|
197
|
-
{
|
|
198
|
-
role: RoleType.User,
|
|
199
|
-
content_type: 'text',
|
|
200
|
-
content: message
|
|
201
|
-
}
|
|
202
|
-
];
|
|
203
|
-
const client = await this.createClient();
|
|
204
|
-
const debugStream = this.debug ? createWriteStream(join(this.debugDir, `sync_${this.formatDateWithMs()}.log`), { flags: 'a' }) : null;
|
|
205
|
-
////如果参数中用的是Workflow,则调用对话流来输出结果
|
|
206
|
-
////否则用智能体的对话来输出结果
|
|
207
|
-
const params = await this.getRequestStream(client, message, callChatOption);
|
|
208
|
-
if (debugStream) {
|
|
209
|
-
debugStream.write(`callChatOption:${JSON.stringify(callChatOption)}\n`);
|
|
210
|
-
debugStream.write(`parameters:${JSON.stringify(params)}\n`);
|
|
211
|
-
}
|
|
212
|
-
const response = this.botid ? await client.chat.create(params as CreateChatReq) : await client.workflows.runs.create(params as RunWorkflowReq);
|
|
213
|
-
if (this.workflowid) {
|
|
214
|
-
const workflowResp = response as RunWorkflowData;
|
|
215
|
-
if (workflowResp.msg === 'Success' || (!workflowResp.msg && workflowResp.data)){
|
|
216
|
-
const resp = workflowResp.data;
|
|
217
|
-
debugStream && debugStream.end(resp);
|
|
218
|
-
return { successed: true, message: [{ role: 'assistant', type: 'answer', content: resp }] };
|
|
219
|
-
}
|
|
220
|
-
debugStream && debugStream.end('workflow run failed');
|
|
221
|
-
console.error('workflow run failed', workflowResp.msg, workflowResp)
|
|
222
|
-
}
|
|
223
|
-
if (!this.workflowid && (response as CreateChatData).conversation_id && (response as CreateChatData).id) {
|
|
224
|
-
const ccd = response as CreateChatData;
|
|
225
|
-
const chatData = await this.getChatDetail(client, ccd.conversation_id, ccd.id);
|
|
226
|
-
if (chatData) {
|
|
227
|
-
const message = chatData.messages.filter(x => x.type === 'answer').map(item => ({
|
|
228
|
-
role: item.role,
|
|
229
|
-
type: item.type,
|
|
230
|
-
content: item.content,
|
|
231
|
-
}));
|
|
232
|
-
return { successed: true, message, usage: chatData.usage, session_id: ccd.conversation_id };
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
debugStream && debugStream.end('聊天未完成');
|
|
236
|
-
return { successed: false, error: { message: '聊天未完成' } };
|
|
237
|
-
|
|
238
|
-
}
|
|
239
|
-
/**
|
|
240
|
-
* 提取XML标签中间的内容,
|
|
241
|
-
* @param xmlStr
|
|
242
|
-
* @param tagName
|
|
243
|
-
* @returns
|
|
244
|
-
*/
|
|
245
|
-
extractXmlContent(xmlStr: string, tagName: string): string {
|
|
246
|
-
// 构建匹配标签的正则(支持任意空白字符和大小写)
|
|
247
|
-
const regex = new RegExp(`<\\s*${tagName}\\s*>([\\s\\S]*?)<\\s*\\/\\s*${tagName}\\s*>`, 'i');
|
|
248
|
-
const match = xmlStr.match(regex);
|
|
249
|
-
if (match && match[1]) return match[1].trim();
|
|
250
|
-
return ''; // 未找到标签或内容
|
|
251
|
-
}
|
|
252
|
-
/**
|
|
253
|
-
* 解析深度思考的JSON内容
|
|
254
|
-
* @param content
|
|
255
|
-
* @param status
|
|
256
|
-
* @returns
|
|
257
|
-
*/
|
|
258
|
-
private parseDeepThinkingJson(content: string) {
|
|
259
|
-
// const thinkingStartIndex = status === DeepThinkingStatus.Thinking ? content.indexOf("{\"process_msg") :
|
|
260
|
-
// (status===DeepThinkingStatus.ReasonOutput ? content.indexOf("{\"reasoning_content") : content.indexOf("{\"card_resource")) ;
|
|
261
|
-
const xmlTagLocation = [content.indexOf(DeepThinkingAction.thinking.start),
|
|
262
|
-
content.indexOf(DeepThinkingAction.reasoning.start),
|
|
263
|
-
content.indexOf(DeepThinkingAction.card.start),
|
|
264
|
-
content.indexOf(DeepThinkingAction.preresponse.start)];
|
|
265
|
-
let minLocation = 10000, minIndex = -1;
|
|
266
|
-
// 找到最小的并且大于0 的位置的下标
|
|
267
|
-
xmlTagLocation.forEach((x, index) => {
|
|
268
|
-
if (x >= 0 && x < minLocation) {
|
|
269
|
-
minLocation = x;
|
|
270
|
-
minIndex = index;
|
|
271
|
-
}
|
|
272
|
-
});
|
|
273
|
-
// const tagLocation = xmlTagLocation.filter(x => x >= 0);
|
|
274
|
-
const thinkingStartIndex = minIndex >= 0 ? minLocation : -1; //tagLocation.length > 0 ? Math.min(...tagLocation) : -1;
|
|
275
|
-
if (thinkingStartIndex < 0) return { content, status: DeepThinkingStatus.ThinkingOver };
|
|
276
|
-
const currentAction = [DeepThinkingAction.thinking, DeepThinkingAction.reasoning, DeepThinkingAction.card, DeepThinkingAction.preresponse][minIndex];
|
|
277
|
-
const currentActionIsOver = content.indexOf(currentAction.end, thinkingStartIndex);
|
|
278
|
-
const thinkingEndIndex = currentActionIsOver >= 0 ? currentActionIsOver : content.indexOf('</', thinkingStartIndex);
|
|
279
|
-
const thinkingContent = this.extractXmlContent(content.substring(thinkingStartIndex, thinkingEndIndex >= 0 ? thinkingEndIndex : undefined) + currentAction.end, currentAction.tag); //"\"}";
|
|
280
|
-
if (currentActionIsOver >= 0) content = content.substring(currentActionIsOver + currentAction.end.length);
|
|
281
|
-
return {
|
|
282
|
-
thinking: {
|
|
283
|
-
action: currentAction,
|
|
284
|
-
text: thinkingContent,//Object.values(thinkingObject)[0]
|
|
285
|
-
completed: currentActionIsOver >= 0
|
|
286
|
-
}, content
|
|
287
|
-
};
|
|
288
|
-
|
|
289
|
-
}
|
|
290
|
-
/**
|
|
291
|
-
*
|
|
292
|
-
* @param date
|
|
293
|
-
* @returns
|
|
294
|
-
*/
|
|
295
|
-
private formatDateWithMs(date = new Date()) {
|
|
296
|
-
// 获取各时间部分
|
|
297
|
-
const year = date.getFullYear(); // 年(4位)
|
|
298
|
-
const month = String(date.getMonth() + 1).padStart(2, '0'); // 月(补0,2位)
|
|
299
|
-
const day = String(date.getDate()).padStart(2, '0'); // 日(补0,2位)
|
|
300
|
-
const hours = String(date.getHours()).padStart(2, '0'); // 时(补0,2位)
|
|
301
|
-
const minutes = String(date.getMinutes()).padStart(2, '0'); // 分(补0,2位)
|
|
302
|
-
const seconds = String(date.getSeconds()).padStart(2, '0'); // 秒(补0,2位)
|
|
303
|
-
const milliseconds = String(date.getMilliseconds()).padStart(3, '0'); // 毫秒(补0,3位)
|
|
304
|
-
|
|
305
|
-
// 拼接成 yyyymmddhhmmssSSS 格式
|
|
306
|
-
return `${year}${month}${day}${hours}${minutes}${seconds}${milliseconds}`;
|
|
307
|
-
}
|
|
308
|
-
/**
|
|
309
|
-
* 流式传输聊天请求
|
|
310
|
-
* @param chatText
|
|
311
|
-
* @param callChatOption
|
|
312
|
-
* @param attach
|
|
313
|
-
* @param _axiosOption
|
|
314
|
-
* @returns
|
|
315
|
-
*/
|
|
316
|
-
override async chatRequestInStream(message: any[] | string, callChatOption: any = {}, attach?: any, _axiosOption?: any): Promise<any> {
|
|
317
|
-
if (!message) this.emit('chaterror', { successed: false, error: 'no message in chat' });
|
|
318
|
-
///如果是字符,则组装成API需要的消息
|
|
319
|
-
if (typeof message === 'string') message = [
|
|
320
|
-
{
|
|
321
|
-
role: RoleType.User,
|
|
322
|
-
content_type: 'text',
|
|
323
|
-
content: message
|
|
324
|
-
}
|
|
325
|
-
];
|
|
326
|
-
const client = await this.createClient();
|
|
327
|
-
////如果参数中用的是Workflow,则调用对话流来输出结果
|
|
328
|
-
////否则用智能体的对话来输出结果
|
|
329
|
-
let requestid = Math.ceil(Math.random() * (new Date().getTime() * Math.random()) / 1000), index = 0;
|
|
330
|
-
const debugStream = this.debug ? createWriteStream(join(this.debugDir, `${this.formatDateWithMs()}.log`), { flags: 'a' }) : null;
|
|
331
|
-
const params = await this.getRequestStream(client, message, callChatOption);
|
|
332
|
-
if (debugStream) {
|
|
333
|
-
debugStream.write(`callChatOption:${JSON.stringify(callChatOption)}\n`);
|
|
334
|
-
debugStream.write(`attach:${attach ? JSON.stringify(attach) : 'null'}\n`);
|
|
335
|
-
debugStream.write(`parameters:${JSON.stringify(params)}\n`);
|
|
336
|
-
}
|
|
337
|
-
const stream = this.botid ? client.chat.stream(params as StreamChatReq) :
|
|
338
|
-
(this.workflowid ? client.workflows.runs.stream(params as RunWorkflowReq) :
|
|
339
|
-
client.workflows.chat.stream(params as ChatWorkflowReq));
|
|
340
|
-
let deltaindex = 0, fullanswer: string[] = [],cardfollowup: string[] = [], followup: string[] = [], cardData: CardType[] = [];
|
|
341
|
-
let deepThinking = '', thinkingStatus = DeepThinkingStatus.None, cardResource = '', preresponseText=''; // 是否在深度思考中
|
|
342
|
-
for await (const part of stream) {
|
|
343
|
-
if (part.event === ChatEventType.ERROR) {
|
|
344
|
-
if (debugStream) debugStream.write('chat error:');
|
|
345
|
-
return this.emit('chaterror', { successed: false, error: 'call failed' });
|
|
346
|
-
}
|
|
347
|
-
if (part.event === ChatEventType.CONVERSATION_MESSAGE_DELTA ||
|
|
348
|
-
part.event === WorkflowEventType.MESSAGE
|
|
349
|
-
) {
|
|
350
|
-
let { conversation_id, content_type, type = 'answer', role = 'assistant', content, reasoning_content: reasoning } = part.data as any;
|
|
351
|
-
if (debugStream) debugStream.write(content);
|
|
352
|
-
if (content === 'Default') continue;
|
|
353
|
-
if (!content && reasoning) {
|
|
354
|
-
this.emit('chatthinking', { text: reasoning, completed: false, action: 'deep-thinking' });
|
|
355
|
-
continue;
|
|
356
|
-
}
|
|
357
|
-
// 如果存在深度思考,则一开始就会带有相关的关键信息
|
|
358
|
-
if (deltaindex === 0 && content.startsWith("<xiaolu-")) {
|
|
359
|
-
thinkingStatus = DeepThinkingStatus.Thinking;
|
|
360
|
-
deltaindex++;
|
|
361
|
-
}
|
|
362
|
-
// 如果在深度思考中,则不输出消息
|
|
363
|
-
if (thinkingStatus === DeepThinkingStatus.Thinking) {
|
|
364
|
-
deepThinking += content;
|
|
365
|
-
const result = this.parseDeepThinkingJson(deepThinking)
|
|
366
|
-
const thinking = result.thinking;
|
|
367
|
-
if (thinking) {
|
|
368
|
-
deepThinking = result.content;
|
|
369
|
-
if (thinking.action === DeepThinkingAction.card) {
|
|
370
|
-
cardResource += result.thinking.text;
|
|
371
|
-
// 卡片流结束,解析卡片资源数据
|
|
372
|
-
if (result.thinking.completed) {
|
|
373
|
-
const allCards = cardResource.replace(/[\x00-\x1F\x7F]/g, '').split('|')
|
|
374
|
-
cardResource='';
|
|
375
|
-
for (const item of allCards) {
|
|
376
|
-
const cardinfo: any = parse(item);
|
|
377
|
-
if (cardinfo.type && cardinfo.tag) {
|
|
378
|
-
if (cardinfo.type === 'follow_up')
|
|
379
|
-
cardfollowup.push(cardinfo.tag);
|
|
380
|
-
else{
|
|
381
|
-
const tags = cardinfo.tag.split(',');
|
|
382
|
-
for (const tag of tags) cardData.push({ type: cardinfo.type, tag })
|
|
383
|
-
//cardData.push({ ...cardinfo })
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
// 将卡片资源返回给客户端
|
|
388
|
-
this.emit('chatcard', cardData);
|
|
389
|
-
}
|
|
390
|
-
} else if(thinking.action === DeepThinkingAction.preresponse){
|
|
391
|
-
/// 当正文一样输出
|
|
392
|
-
const spiltPreresponse = result.thinking.text.slice(preresponseText.length)
|
|
393
|
-
preresponseText = result.thinking.text;
|
|
394
|
-
fullanswer.push(spiltPreresponse);// = [result.thinking.text];// .push(result.thinking.text);
|
|
395
|
-
let output = { successed: true, type, content_type, role, requestid, segment: spiltPreresponse, text: fullanswer.join(''), index: index++, session_id: conversation_id, preresponse: true, preresponseover: result.thinking.completed };
|
|
396
|
-
if (attach) output = Object.assign({}, output, attach);
|
|
397
|
-
this.emit('chattext', output)
|
|
398
|
-
}
|
|
399
|
-
else {
|
|
400
|
-
this.emit('chatthinking', { text: result.thinking.text, completed: result.thinking.completed, action: thinking.action?.tag });
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
if (result.status != DeepThinkingStatus.ThinkingOver) continue;
|
|
404
|
-
thinkingStatus = DeepThinkingStatus.ThinkingOver;
|
|
405
|
-
// 将排除了thinking之后的消息内容要带下去成为正式的输出内容
|
|
406
|
-
content = deepThinking;
|
|
407
|
-
}
|
|
408
|
-
fullanswer.push(content);
|
|
409
|
-
let output = { successed: true, type, content_type, role, requestid, segment: content, text: fullanswer.join(''), index: index++, session_id: conversation_id };
|
|
410
|
-
if (attach) output = Object.assign({}, output, attach);
|
|
411
|
-
this.emit('chattext', output)
|
|
412
|
-
}
|
|
413
|
-
////在流式传输中,提取相关推荐问题
|
|
414
|
-
if (part.event === ChatEventType.CONVERSATION_MESSAGE_COMPLETED) {
|
|
415
|
-
const { type, content } = part.data ?? {};
|
|
416
|
-
if (type === 'follow_up') {
|
|
417
|
-
if (debugStream) debugStream.write('followup:' + content);
|
|
418
|
-
followup.push(content);
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
///整个对话结束
|
|
422
|
-
if (part.event === ChatEventType.CONVERSATION_CHAT_COMPLETED ||
|
|
423
|
-
part.event === WorkflowEventType.DONE
|
|
424
|
-
) {
|
|
425
|
-
const { conversation_id, content } = (part.data) ?? {} as any;
|
|
426
|
-
let output = { successed: true, cards: cardData.length ? cardData : null, cardfollowup: cardfollowup.filter(x=>typeof x === 'string' && x.length > 0), followup, type: 'answer', content_type: 'text', role: RoleType.Assistant, requestid, segment: null, text: content ?? fullanswer.join(''), index: index++, session_id: conversation_id };
|
|
427
|
-
if (attach) output = Object.assign({}, output, attach);
|
|
428
|
-
if (debugStream) debugStream.end('chat completed');
|
|
429
|
-
this.emit('chatdone', output)
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
return { successed: true, requestid }
|
|
433
|
-
}
|
|
434
|
-
}
|