@blueking/ai-ui-sdk 0.0.9-beta.1 → 0.0.9-beta.2
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/README.md +420 -0
- package/dist/main.js +1 -1
- package/package.json +1 -1
package/README.md
ADDED
@@ -0,0 +1,420 @@
|
|
1
|
+
# 蓝鲸 AI UI SDK
|
2
|
+
|
3
|
+
## 介绍
|
4
|
+
|
5
|
+
蓝鲸 AI UI SDK (@blueking/ai-ui-sdk) 是一个用于快速构建 AI 应用前端界面的工具包。它提供了一系列组件和 hooks,帮助开发者简化 AI 聊天界面的开发过程,包括聊天功能、引用资料展示、AI 思考过程可视化等功能。
|
6
|
+
|
7
|
+
## 安装
|
8
|
+
|
9
|
+
```bash
|
10
|
+
npm install @blueking/ai-ui-sdk
|
11
|
+
```
|
12
|
+
|
13
|
+
## 主要功能
|
14
|
+
|
15
|
+
- **聊天功能**:管理 AI 对话的完整生命周期
|
16
|
+
- **引用资料展示**:显示 AI 在回答中引用的文档资料
|
17
|
+
- **思考过程可视化**:展示 AI 的思考过程和推理步骤
|
18
|
+
- **内容总结**:快速对对话内容进行摘要总结
|
19
|
+
- **统一样式**:提供一致的 UI 样式和图标
|
20
|
+
- **可拖拽和缩放的聊天窗口**:支持自定义位置和大小的聊天界面
|
21
|
+
- **快捷指令功能**:支持预设的快捷操作和自定义指令
|
22
|
+
- **多语言支持**:内置国际化支持
|
23
|
+
|
24
|
+
## 使用指南
|
25
|
+
|
26
|
+
### 基本设置
|
27
|
+
|
28
|
+
```typescript
|
29
|
+
import { useStyle, useChat, useClickProxy } from '@blueking/ai-ui-sdk';
|
30
|
+
|
31
|
+
// 引入样式和图标
|
32
|
+
useStyle();
|
33
|
+
|
34
|
+
// 设置全局点击代理事件
|
35
|
+
useClickProxy();
|
36
|
+
|
37
|
+
// 初始化聊天
|
38
|
+
const {
|
39
|
+
currentSession,
|
40
|
+
sessionContents,
|
41
|
+
sendChat,
|
42
|
+
stopChat,
|
43
|
+
setCurrentSession,
|
44
|
+
currentSessionLoading,
|
45
|
+
reGenerateChat,
|
46
|
+
reSendChat,
|
47
|
+
deleteChat,
|
48
|
+
} = useChat({
|
49
|
+
handleStart: () => {
|
50
|
+
console.log('聊天开始');
|
51
|
+
},
|
52
|
+
handleText: () => {
|
53
|
+
console.log('收到文本消息');
|
54
|
+
},
|
55
|
+
handleEnd: () => {
|
56
|
+
console.log('聊天结束');
|
57
|
+
},
|
58
|
+
requestOptions: {
|
59
|
+
url: 'your-api-endpoint',
|
60
|
+
},
|
61
|
+
});
|
62
|
+
```
|
63
|
+
|
64
|
+
### 创建聊天会话
|
65
|
+
|
66
|
+
```typescript
|
67
|
+
// 设置当前会话
|
68
|
+
const session: ISession = {
|
69
|
+
sessionCode: '1',
|
70
|
+
sessionName: 'test',
|
71
|
+
model: '',
|
72
|
+
};
|
73
|
+
setCurrentSession(session);
|
74
|
+
|
75
|
+
// 发送聊天消息
|
76
|
+
sendChat({
|
77
|
+
message: '你的问题',
|
78
|
+
cite: '选中的文本', // 可选,引用的文本内容
|
79
|
+
});
|
80
|
+
|
81
|
+
// 使用快捷指令发送消息
|
82
|
+
sendChat({
|
83
|
+
message: '快捷指令标签',
|
84
|
+
cite: '选中的文本',
|
85
|
+
shortcut: {
|
86
|
+
label: '快捷指令名称',
|
87
|
+
key: 'shortcut-key',
|
88
|
+
prompt: '预设的提示模板',
|
89
|
+
icon: '图标', // 可选
|
90
|
+
},
|
91
|
+
});
|
92
|
+
|
93
|
+
// 停止正在进行的聊天
|
94
|
+
stopChat(session.sessionCode);
|
95
|
+
```
|
96
|
+
|
97
|
+
### 完整的聊天界面示例
|
98
|
+
|
99
|
+
```vue
|
100
|
+
<template>
|
101
|
+
<div class="ai-blueking-wrapper">
|
102
|
+
<vue-draggable-resizable
|
103
|
+
v-if="isShow"
|
104
|
+
:active="isShow"
|
105
|
+
:draggable="true"
|
106
|
+
:h="height"
|
107
|
+
:min-height="minHeight"
|
108
|
+
:min-width="minWidth"
|
109
|
+
:parent="true"
|
110
|
+
:prevent-deactivation="true"
|
111
|
+
:resizable="true"
|
112
|
+
:w="width"
|
113
|
+
:x="left"
|
114
|
+
:y="top"
|
115
|
+
class-name="ai-blueking-container-wrapper"
|
116
|
+
drag-handle=".drag-handle"
|
117
|
+
@dragging="handleDragging"
|
118
|
+
@resizing="handleResizing"
|
119
|
+
>
|
120
|
+
<div class="ai-blueking-container">
|
121
|
+
<!-- 聊天界面内容 -->
|
122
|
+
<div class="content-wrapper">
|
123
|
+
<div class="message-wrapper">
|
124
|
+
<render-message
|
125
|
+
v-for="(message, index) in sessionContents"
|
126
|
+
:key="message.id"
|
127
|
+
:message="message"
|
128
|
+
:index="index"
|
129
|
+
@delete="handleDelete"
|
130
|
+
@regenerate="handleRegenerate"
|
131
|
+
@resend="handleResend"
|
132
|
+
/>
|
133
|
+
</div>
|
134
|
+
|
135
|
+
<div class="chat-input-container">
|
136
|
+
<ChatInputBox
|
137
|
+
v-model="inputMessage"
|
138
|
+
:loading="currentSessionLoading"
|
139
|
+
:shortcuts="shortcuts"
|
140
|
+
@send="handleSendMessage"
|
141
|
+
@shortcut-click="handleShortcutClick"
|
142
|
+
@stop="handleStop"
|
143
|
+
/>
|
144
|
+
</div>
|
145
|
+
</div>
|
146
|
+
</div>
|
147
|
+
</vue-draggable-resizable>
|
148
|
+
</div>
|
149
|
+
</template>
|
150
|
+
```
|
151
|
+
|
152
|
+
### 快捷指令配置
|
153
|
+
|
154
|
+
```typescript
|
155
|
+
// 默认快捷指令示例
|
156
|
+
const DEFAULT_SHORTCUTS: ShortCut[] = [
|
157
|
+
{
|
158
|
+
label: '解释代码',
|
159
|
+
key: 'explain-code',
|
160
|
+
prompt: '请解释以下代码的功能:{ SELECTED_TEXT }',
|
161
|
+
icon: 'code-icon',
|
162
|
+
},
|
163
|
+
// 更多快捷指令...
|
164
|
+
];
|
165
|
+
|
166
|
+
// 在组件中使用
|
167
|
+
const props = defineProps<{
|
168
|
+
shortcuts?: ShortCut[];
|
169
|
+
}>();
|
170
|
+
```
|
171
|
+
|
172
|
+
## 类型定义
|
173
|
+
|
174
|
+
### 会话类型
|
175
|
+
|
176
|
+
```typescript
|
177
|
+
interface ISession {
|
178
|
+
sessionCode: string;
|
179
|
+
sessionName: string;
|
180
|
+
model: string;
|
181
|
+
roleInfo?: {
|
182
|
+
collectionId: number;
|
183
|
+
collectionName: string;
|
184
|
+
content: ISessionPrompt[];
|
185
|
+
variables: any[];
|
186
|
+
};
|
187
|
+
}
|
188
|
+
```
|
189
|
+
|
190
|
+
### 聊天内容类型
|
191
|
+
|
192
|
+
```typescript
|
193
|
+
interface ISessionContent {
|
194
|
+
id?: number;
|
195
|
+
role: SessionContentRole;
|
196
|
+
content: string;
|
197
|
+
status?: SessionContentStatus;
|
198
|
+
sessionCode: string;
|
199
|
+
cite?: string;
|
200
|
+
time?: string;
|
201
|
+
}
|
202
|
+
```
|
203
|
+
|
204
|
+
### 快捷指令类型
|
205
|
+
|
206
|
+
```typescript
|
207
|
+
interface ShortCut {
|
208
|
+
label: string;
|
209
|
+
key: string;
|
210
|
+
prompt: string;
|
211
|
+
icon?: string;
|
212
|
+
}
|
213
|
+
```
|
214
|
+
|
215
|
+
## 高级功能
|
216
|
+
|
217
|
+
### 消息重发和重新生成
|
218
|
+
|
219
|
+
```typescript
|
220
|
+
// 重新生成 AI 回复
|
221
|
+
const handleRegenerate = (index: number) => {
|
222
|
+
reGenerateChat(index);
|
223
|
+
};
|
224
|
+
|
225
|
+
// 重新发送用户消息
|
226
|
+
const handleResend = (index: number, value: { message: string; cite: string }) => {
|
227
|
+
reSendChat(index, value);
|
228
|
+
};
|
229
|
+
```
|
230
|
+
|
231
|
+
### 消息删除
|
232
|
+
|
233
|
+
```typescript
|
234
|
+
const handleDelete = (index: number) => {
|
235
|
+
deleteChat(index);
|
236
|
+
};
|
237
|
+
```
|
238
|
+
|
239
|
+
## 样式定制
|
240
|
+
|
241
|
+
SDK 提供了基础的样式和主题支持,你可以通过覆盖 CSS 变量来自定义界面外观:
|
242
|
+
|
243
|
+
```scss
|
244
|
+
.ai-blueking-container {
|
245
|
+
// 自定义样式
|
246
|
+
}
|
247
|
+
|
248
|
+
.message-wrapper {
|
249
|
+
// 消息列表样式
|
250
|
+
}
|
251
|
+
|
252
|
+
.chat-input-container {
|
253
|
+
// 输入框样式
|
254
|
+
}
|
255
|
+
```
|
256
|
+
|
257
|
+
## 对话组件示例
|
258
|
+
|
259
|
+
### 示例:使用 `useChat` Hook
|
260
|
+
|
261
|
+
以下是一个完整的对话组件示例,展示了如何正确使用 `useChat` hook。该示例包括如何设置会话、发送消息、处理回调以及配置请求选项。
|
262
|
+
|
263
|
+
```typescript
|
264
|
+
import { useStyle, useChat } from '@blueking/ai-ui-sdk';
|
265
|
+
|
266
|
+
// 引入样式和图标
|
267
|
+
useStyle();
|
268
|
+
|
269
|
+
// 初始化聊天
|
270
|
+
const {
|
271
|
+
currentSession,
|
272
|
+
sessionContents,
|
273
|
+
sendChat,
|
274
|
+
stopChat,
|
275
|
+
setCurrentSession,
|
276
|
+
currentSessionLoading,
|
277
|
+
reGenerateChat,
|
278
|
+
reSendChat,
|
279
|
+
deleteChat,
|
280
|
+
} = useChat({
|
281
|
+
handleStart: () => {
|
282
|
+
scrollToBottomIfNeeded();
|
283
|
+
},
|
284
|
+
handleText: () => {
|
285
|
+
scrollToBottomIfNeeded();
|
286
|
+
},
|
287
|
+
handleEnd: () => {
|
288
|
+
scrollToBottomIfNeeded();
|
289
|
+
},
|
290
|
+
requestOptions: {
|
291
|
+
url: props.url,
|
292
|
+
},
|
293
|
+
});
|
294
|
+
|
295
|
+
// 设置当前会话
|
296
|
+
const session: ISession = {
|
297
|
+
sessionCode: '1',
|
298
|
+
sessionName: 'test',
|
299
|
+
model: '',
|
300
|
+
};
|
301
|
+
setCurrentSession(session);
|
302
|
+
|
303
|
+
// 发送聊天消息
|
304
|
+
sendChat({
|
305
|
+
message: '你的问题',
|
306
|
+
cite: '选中的文本', // 可选,引用的文本内容
|
307
|
+
});
|
308
|
+
|
309
|
+
// 使用快捷指令发送消息
|
310
|
+
sendChat({
|
311
|
+
message: '快捷指令标签',
|
312
|
+
cite: '选中的文本',
|
313
|
+
shortcut: {
|
314
|
+
label: '快捷指令名称',
|
315
|
+
key: 'shortcut-key',
|
316
|
+
prompt: '预设的提示模板',
|
317
|
+
icon: '图标', // 可选
|
318
|
+
},
|
319
|
+
});
|
320
|
+
|
321
|
+
// 停止正在进行的聊天
|
322
|
+
stopChat(session.sessionCode);
|
323
|
+
|
324
|
+
// 重新生成 AI 回复
|
325
|
+
const handleRegenerate = (index: number) => {
|
326
|
+
reGenerateChat(index);
|
327
|
+
};
|
328
|
+
|
329
|
+
// 重新发送用户消息
|
330
|
+
const handleResend = (index: number, value: { message: string; cite: string }) => {
|
331
|
+
reSendChat(index, value);
|
332
|
+
};
|
333
|
+
|
334
|
+
// 删除消息
|
335
|
+
const handleDelete = (index: number) => {
|
336
|
+
deleteChat(index);
|
337
|
+
};
|
338
|
+
|
339
|
+
// 滚动到底部
|
340
|
+
const scrollToBottomIfNeeded = () => {
|
341
|
+
// 实现滚动到底部的逻辑
|
342
|
+
};
|
343
|
+
```
|
344
|
+
|
345
|
+
### 代码说明
|
346
|
+
|
347
|
+
- **`useStyle()`**: 引入 SDK 的样式和图标。
|
348
|
+
- **`useChat()`**: 初始化聊天功能,返回多个方法和状态用于管理聊天会话。
|
349
|
+
- **`currentSession`**: 当前会话对象。
|
350
|
+
- **`sessionContents`**: 当前会话中的所有消息内容。
|
351
|
+
- **`sendChat()`**: 发送聊天消息。
|
352
|
+
- **`stopChat()`**: 停止正在进行的聊天。
|
353
|
+
- **`setCurrentSession()`**: 设置当前会话。
|
354
|
+
- **`currentSessionLoading`**: 当前会话是否正在加载。
|
355
|
+
- **`reGenerateChat()`**: 重新生成 AI 回复。
|
356
|
+
- **`reSendChat()`**: 重新发送用户消息。
|
357
|
+
- **`deleteChat()`**: 删除消息。
|
358
|
+
- **`handleStart`**: 聊天开始时的回调函数。
|
359
|
+
- **`handleText`**: 收到文本消息时的回调函数。
|
360
|
+
- **`handleEnd`**: 聊天结束时的回调函数。
|
361
|
+
- **`requestOptions`**: 配置请求选项,包括 API 的 URL。
|
362
|
+
|
363
|
+
## 注意事项
|
364
|
+
|
365
|
+
- SDK 依赖 Vue 3,请确保项目中已安装
|
366
|
+
- 建议使用 TypeScript 以获得更好的类型提示
|
367
|
+
|
368
|
+
## 版本升级指南
|
369
|
+
|
370
|
+
### 从 0.9.x 升级到 1.0.0
|
371
|
+
|
372
|
+
1. **更新依赖**:
|
373
|
+
```bash
|
374
|
+
npm install @blueking/ai-ui-sdk@1.0.0
|
375
|
+
```
|
376
|
+
|
377
|
+
2. **迁移指南**:
|
378
|
+
- `useChat` hook 的 `requestOptions` 参数现在需要包含 `url` 属性。
|
379
|
+
- 移除了 `useClickProxy`,请使用新的 `useGlobalClickHandler`。
|
380
|
+
- 新增了 `useStyle` 的 `theme` 参数,用于自定义主题。
|
381
|
+
|
382
|
+
3. **示例**:
|
383
|
+
```typescript
|
384
|
+
import { useStyle, useChat } from '@blueking/ai-ui-sdk';
|
385
|
+
|
386
|
+
// 引入样式和图标
|
387
|
+
useStyle({ theme: 'dark' });
|
388
|
+
|
389
|
+
// 初始化聊天
|
390
|
+
const {
|
391
|
+
currentSession,
|
392
|
+
sessionContents,
|
393
|
+
sendChat,
|
394
|
+
stopChat,
|
395
|
+
setCurrentSession,
|
396
|
+
currentSessionLoading,
|
397
|
+
reGenerateChat,
|
398
|
+
reSendChat,
|
399
|
+
deleteChat,
|
400
|
+
} = useChat({
|
401
|
+
handleStart: () => {
|
402
|
+
console.log('聊天开始');
|
403
|
+
},
|
404
|
+
handleText: () => {
|
405
|
+
console.log('收到文本消息');
|
406
|
+
},
|
407
|
+
handleEnd: () => {
|
408
|
+
console.log('聊天结束');
|
409
|
+
},
|
410
|
+
requestOptions: {
|
411
|
+
url: 'your-api-endpoint',
|
412
|
+
},
|
413
|
+
});
|
414
|
+
```
|
415
|
+
|
416
|
+
4. **常见问题**:
|
417
|
+
- **Q: 如何处理 API 请求失败?**
|
418
|
+
- A: 使用 `try-catch` 块捕获 `sendChat` 和 `reGenerateChat` 的错误。
|
419
|
+
- **Q: 如何自定义聊天窗口的样式?**
|
420
|
+
- A: 通过覆盖 CSS 变量来自定义界面外观。
|
package/dist/main.js
CHANGED
@@ -243,6 +243,6 @@ url(${D}) format("embedded-opentype");
|
|
243
243
|
&~ .knowledge-head {
|
244
244
|
margin-bottom: 8px;
|
245
245
|
}
|
246
|
-
}`;(A=document.createElement("style")).textContent=e,document.head.appendChild(A)},i=()=>{A&&(A.remove(),A=null)};(0,T.onBeforeMount)(()=>{e()}),(0,T.onBeforeUnmount)(()=>{i()})};function L(A,e,i,t,n,o,g){try{var l=A[o](g),a=l.value}catch(A){i(A);return}l.done?e(a):Promise.resolve(a).then(t,n)}function Y(A){return function(){var e=this,i=arguments;return new Promise(function(t,n){var o=A.apply(e,i);function g(A){L(o,t,n,g,l,"next",A)}function l(A){L(o,t,n,g,l,"throw",A)}g(void 0)})}}function O(A,e,i){return e in A?Object.defineProperty(A,e,{value:i,enumerable:!0,configurable:!0,writable:!0}):A[e]=i,A}class f{stream({sessionCode:A,url:e,headers:i,data:t}){var n=this;return Y(function*(){var o,g;yield null===(o=n.handleStart)||void 0===o?void 0:o.call(n,A);let l=new AbortController;n.controllerMap[A]=l,fetch(e,{method:"post",signal:l.signal,headers:function(A){for(var e=1;e<arguments.length;e++){var i=null!=arguments[e]?arguments[e]:{},t=Object.keys(i);"function"==typeof Object.getOwnPropertySymbols&&(t=t.concat(Object.getOwnPropertySymbols(i).filter(function(A){return Object.getOwnPropertyDescriptor(i,A).enumerable}))),t.forEach(function(e){O(A,e,i[e])})}return A}({"Content-Type":"application/json"},i),mode:"cors",credentials:"include",body:JSON.stringify(t)}).then((g=Y(function*(e){let i=e.body.pipeThrough(new window.TextDecoderStream).getReader(),t="";for(;;)try{let{value:o,done:g}=yield i.read();if(!e.ok){n.handleError(A,o||e.statusText,e.status);break}if(g){n.handleEnd(A);break}(t+o.toString()).split("\n").forEach(i=>{let o=i.replace("data:","").trim();if(C(o)){var g,l;let{event:i,content:a,cover:M,documents:s,result:c,code:u,elapsed_time:r,message:N}=JSON.parse(o);if(!1===c||200!==e.status){n.handleError(A,N||"模型调用失败",u);return}switch(i){case"text":n.handleText(A,a,M);break;case"reference_doc":null===(g=n.handleReferenceDoc)||void 0===g||g.call(n,A,s,M);break;case"think":null===(l=n.handleThink)||void 0===l||l.call(n,A,a,M,r);break;case"done":n.handleEnd(A,M?a:"");break;case"error":n.handleError(A,N||"模型调用失败",u)}t=""}else o&&(t=o)})}catch(e){(null==e?void 0:e.code)!==20&&n.handleError(A,`模型调用失败:${e.message}`,e.code);break}}),function(A){return g.apply(this,arguments)}))})()}stop(A){var e,i;return null===(i=this.controllerMap[A])||void 0===i||null===(e=i.abort)||void 0===e||e.call(i),this.handleEnd(A)}constructor({handleStart:A,handleText:e,handleReferenceDoc:i,handleThink:t,handleEnd:n,handleError:o}){O(this,"handleStart",void 0),O(this,"handleText",void 0),O(this,"handleReferenceDoc",void 0),O(this,"handleThink",void 0),O(this,"handleEnd",void 0),O(this,"handleError",void 0),O(this,"controllerMap",void 0),this.handleStart=A,this.handleText=e,this.handleReferenceDoc=i,this.handleThink=t,this.handleEnd=n,this.handleError=o,this.controllerMap={}}}let b=({handleStart:A,handleText:e,handleReferenceDoc:i,handleThink:t,handleEnd:n,handleError:o,requestOptions:g}={})=>{let l="内容正在生成中...",a=(0,T.ref)(),M=(0,T.ref)({}),s=(0,T.ref)([]),N={},d=(0,T.computed)(()=>{let A=[];for(let e=s.value.length-1;e>=0;e--){let i=s.value[e],t=e+1,n=s.value[t];for(;n&&![u.Ai,u.TokenExpired,u.ImageNotSupported,u.Pause,u.Guide].includes(n.role);)t+=1,n=s.value[t];if(i.role===u.System)break;i.status===c.Fail||(null==n?void 0:n.status)===c.Fail&&[u.User,u.UserImage].includes(i.role)||[u.Time,u.System].includes(i.role)||A.unshift(i)}return A}),I=(0,T.computed)(()=>{var A;let e=null===(A=a.value)||void 0===A?void 0:A.sessionCode;return!!e&&M.value[e]}),D=(0,T.computed)(()=>{var A,e,i;let t=[],n=[],o=[],g=s.value.findLastIndex(A=>A.role===u.System&&["已启用角色","已启用模型"].some(e=>A.content.includes(e))),l=0;null===(i=a.value)||void 0===i||null===(e=i.roleInfo)||void 0===e||null===(A=e.content)||void 0===A||A.forEach(A=>{let e=s.value[g+1+l],i=s.value[g+2+l];if((null==e?void 0:e.content)===A.content&&e.role!==u.System&&(t.push(j(e)),l+=1,(null==e?void 0:e.role)===u.Pause)){for(;i&&i.role===u.System;)l+=1,i=s.value[g+1+l];for(;i&&[u.User,u.UserImage].includes(i.role);)t.push(j(i)),l+=1,i=s.value[g+1+l]}}),n.push(...d.value.map(j));let M=A=>{let e=!0;for(let o=A;o<t.length;o++){var i;t[o].content!==(null===(i=n[o-A])||void 0===i?void 0:i.content)&&(e=!1)}return e};for(let A=0;A<t.length;A++){let e=t[A];if(M(A))break;o.push(e)}return o.push(...n),o.forEach(A=>{A.content=m(A.content),A.content=z(A.content)}),o}),E=new f({handleStart:w,handleText:function(A,i,t){let n=B(A);if(n.content===l)n.content=i;else{if(n.status!==c.Loading)return;n.content=t?i:n.content+i}return null==e?void 0:e(A,n)},handleReferenceDoc:function(A,e,t){let n=B(A),o=h(e);return n.content=t?o:n.content+o,null==i?void 0:i(A,n)},handleThink:function(A,e,i,n){let o=B(A);return o.content=k(o.content,e,i,n),null==t?void 0:t(A,o)},handleEnd:function(A,e){let i=B(A);if(i.status===c.Loading)return M.value[A]=!1,e&&(i.content=e),i.status=c.Success,null==n?void 0:n(A,i)
|
246
|
+
}`;(A=document.createElement("style")).textContent=e,document.head.appendChild(A)},i=()=>{A&&(A.remove(),A=null)};(0,T.onBeforeMount)(()=>{e()}),(0,T.onBeforeUnmount)(()=>{i()})};function L(A,e,i,t,n,o,g){try{var l=A[o](g),a=l.value}catch(A){i(A);return}l.done?e(a):Promise.resolve(a).then(t,n)}function Y(A){return function(){var e=this,i=arguments;return new Promise(function(t,n){var o=A.apply(e,i);function g(A){L(o,t,n,g,l,"next",A)}function l(A){L(o,t,n,g,l,"throw",A)}g(void 0)})}}function O(A,e,i){return e in A?Object.defineProperty(A,e,{value:i,enumerable:!0,configurable:!0,writable:!0}):A[e]=i,A}class f{stream({sessionCode:A,url:e,headers:i,data:t}){var n=this;return Y(function*(){var o,g;yield null===(o=n.handleStart)||void 0===o?void 0:o.call(n,A);let l=new AbortController;n.controllerMap[A]=l,fetch(e,{method:"post",signal:l.signal,headers:function(A){for(var e=1;e<arguments.length;e++){var i=null!=arguments[e]?arguments[e]:{},t=Object.keys(i);"function"==typeof Object.getOwnPropertySymbols&&(t=t.concat(Object.getOwnPropertySymbols(i).filter(function(A){return Object.getOwnPropertyDescriptor(i,A).enumerable}))),t.forEach(function(e){O(A,e,i[e])})}return A}({"Content-Type":"application/json"},i),mode:"cors",credentials:"include",body:JSON.stringify(t)}).then((g=Y(function*(e){let i=e.body.pipeThrough(new window.TextDecoderStream).getReader(),t="";for(;;)try{let{value:o,done:g}=yield i.read();if(!e.ok){n.handleError(A,o||e.statusText,e.status);break}if(g){n.handleEnd(A);break}(t+o.toString()).split("\n").forEach(i=>{let o=i.replace("data:","").trim();if(C(o)){var g,l;let{event:i,content:a,cover:M,documents:s,result:c,code:u,elapsed_time:r,message:N}=JSON.parse(o);if(!1===c||200!==e.status){n.handleError(A,N||"模型调用失败",u);return}switch(i){case"text":n.handleText(A,a,M);break;case"reference_doc":null===(g=n.handleReferenceDoc)||void 0===g||g.call(n,A,s,M);break;case"think":null===(l=n.handleThink)||void 0===l||l.call(n,A,a,M,r);break;case"done":n.handleEnd(A,M?a:"");break;case"error":n.handleError(A,N||"模型调用失败",u)}t=""}else o&&(t=o)})}catch(e){(null==e?void 0:e.code)!==20&&n.handleError(A,`模型调用失败:${e.message}`,e.code);break}}),function(A){return g.apply(this,arguments)}))})()}stop(A){var e,i;return null===(i=this.controllerMap[A])||void 0===i||null===(e=i.abort)||void 0===e||e.call(i),this.handleEnd(A)}constructor({handleStart:A,handleText:e,handleReferenceDoc:i,handleThink:t,handleEnd:n,handleError:o}){O(this,"handleStart",void 0),O(this,"handleText",void 0),O(this,"handleReferenceDoc",void 0),O(this,"handleThink",void 0),O(this,"handleEnd",void 0),O(this,"handleError",void 0),O(this,"controllerMap",void 0),this.handleStart=A,this.handleText=e,this.handleReferenceDoc=i,this.handleThink=t,this.handleEnd=n,this.handleError=o,this.controllerMap={}}}let b=({handleStart:A,handleText:e,handleReferenceDoc:i,handleThink:t,handleEnd:n,handleError:o,requestOptions:g}={})=>{let l="内容正在生成中...",a=(0,T.ref)(),M=(0,T.ref)({}),s=(0,T.ref)([]),N={},d=(0,T.computed)(()=>{let A=[];for(let e=s.value.length-1;e>=0;e--){let i=s.value[e],t=e+1,n=s.value[t];for(;n&&![u.Ai,u.TokenExpired,u.ImageNotSupported,u.Pause,u.Guide].includes(n.role);)t+=1,n=s.value[t];if(i.role===u.System)break;i.status===c.Fail||(null==n?void 0:n.status)===c.Fail&&[u.User,u.UserImage].includes(i.role)||[u.Time,u.System].includes(i.role)||A.unshift(i)}return A}),I=(0,T.computed)(()=>{var A;let e=null===(A=a.value)||void 0===A?void 0:A.sessionCode;return!!e&&M.value[e]}),D=(0,T.computed)(()=>{var A,e,i;let t=[],n=[],o=[],g=s.value.findLastIndex(A=>A.role===u.System&&["已启用角色","已启用模型"].some(e=>A.content.includes(e))),l=0;null===(i=a.value)||void 0===i||null===(e=i.roleInfo)||void 0===e||null===(A=e.content)||void 0===A||A.forEach(A=>{let e=s.value[g+1+l],i=s.value[g+2+l];if((null==e?void 0:e.content)===A.content&&e.role!==u.System&&(t.push(j(e)),l+=1,(null==e?void 0:e.role)===u.Pause)){for(;i&&i.role===u.System;)l+=1,i=s.value[g+1+l];for(;i&&[u.User,u.UserImage].includes(i.role);)t.push(j(i)),l+=1,i=s.value[g+1+l]}}),n.push(...d.value.map(j));let M=A=>{let e=!0;for(let o=A;o<t.length;o++){var i;t[o].content!==(null===(i=n[o-A])||void 0===i?void 0:i.content)&&(e=!1)}return e};for(let A=0;A<t.length;A++){let e=t[A];if(M(A))break;o.push(e)}return o.push(...n),o.forEach(A=>{A.content=m(A.content),A.content=z(A.content)}),o}),E=new f({handleStart:w,handleText:function(A,i,t){let n=B(A);if(n.content===l)n.content=i;else{if(n.status!==c.Loading)return;n.content=t?i:n.content+i}return null==e?void 0:e(A,n)},handleReferenceDoc:function(A,e,t){let n=B(A),o=h(e);return n.content=t?o:n.content+o,null==i?void 0:i(A,n)},handleThink:function(A,e,i,n){let o=B(A);return o.content=k(o.content,e,i,n),null==t?void 0:t(A,o)},handleEnd:function(A,e){let i=B(A);if(i.status===c.Loading)return M.value[A]=!1,(i.content===l||x(i.content))&&v(A,"聊天内容已中断"),e&&(i.content=e),i.status=c.Success,null==n?void 0:n(A,i)},handleError:v});function B(A){var e,i;return(null===(e=a.value)||void 0===e?void 0:e.sessionCode)===A?s.value.at(-1):null===(i=N[A])||void 0===i?void 0:i.at(-1)}function C(A){var e;return(null===(e=a.value)||void 0===e?void 0:e.sessionCode)===A?s.value:N[A]}function Q(A,e){C(A).push(e)}function p(A,e,i){var t;let n=(null===(t=a.value)||void 0===t?void 0:t.sessionCode)===A?s.value:N[A],o=[];return e.forEach(A=>{let e=n.findIndex(e=>e.id===A);if(e>-1){let t=n[e-1],g=n[e+1],l=n[e+2];if(n.splice(e,1),o.push(A),[u.Hidden].includes(null==t?void 0:t.role)){let A=n.findIndex(A=>A.id===t.id);n.splice(A,1),o.push(t.id)}if((null==g?void 0:g.role)===u.Ai||i&&[u.Ai,u.Guide,u.TokenExpired,u.ImageNotSupported,u.Pause].includes(null==g?void 0:g.role)){let A=n.findIndex(A=>A.id===g.id);n.splice(A,1),o.push(g.id)}if([u.Guide].includes(null==l?void 0:l.role)&&i){let A=n.findIndex(A=>A.id===l.id);n.splice(A,1),o.push(l.id)}}}),o}function w(e){M.value[e]=!0;let i={sessionCode:e,role:u.Ai,status:c.Loading,content:l};return Q(e,i),null==A?void 0:A(e,i)}function v(A,e,i){let t=B(A);return t.status=c.Fail,t.content=e,M.value[A]=!1,i===r.TokenExpired&&(t.content="抱歉,您的剩余 Token 不足,无法返回回答内容,请先清空当前会话(上下文仍会作为历史记录保留))",t.role=u.TokenExpired),i===r.ImageNotSupported&&(t.content="抱歉,当前模型不支持图片内容解析",t.role=u.ImageNotSupported),null==o?void 0:o(A,t,i)}function L(A,e){var i,t,n;if(!(null===(i=a.value)||void 0===i?void 0:i.sessionCode)||!(null==g?void 0:g.url)||I.value)return;let{message:o,cite:l,shortcut:M}=A,r="";r=M?y(M.prompt,l):l?`${o}: "${l}"`:o,s.value.push({sessionCode:null===(t=a.value)||void 0===t?void 0:t.sessionCode,content:o,role:u.User,status:c.Success,cite:l}),E.stream({sessionCode:null===(n=a.value)||void 0===n?void 0:n.sessionCode,url:g.url,headers:null==g?void 0:g.headers,data:{inputs:{chat_history:D.value.slice(0,D.value.length-1),input:r}}}),null==e||e()}return{currentSession:a,sessionContents:s,sessionContentsMap:N,sessionLoadingMap:M,prompts:D,currentSessionLoading:I,chat:function({sessionCode:A,data:e,url:i,headers:t}){E.stream({sessionCode:A,url:i,data:e,headers:t||(null==g?void 0:g.headers)})},sendChat:L,stopChat:function(A){E.stop(A)},plusSessionContent:Q,updateSessionContent:function(A){var e;let i=((null===(e=a.value)||void 0===e?void 0:e.sessionCode)===A.sessionCode?s.value:N[A.sessionCode]).find(e=>+(e.id||0)==+(A.id||0));i&&Object.assign(i,A)},getSessionContentById:function(A,e){return C(e).find(e=>e.id===A)},getLastSessionContentBySessionCode:B,getSessionContentsBySessionCode:C,setCurrentSession:function(A){a.value=A,(null==A?void 0:A.sessionCode)&&(N[A.sessionCode]||(N[A.sessionCode]=[]),s.value=N[A.sessionCode])},setSessionContents:function(A){a.value&&(N[a.value.sessionCode]=A,s.value=A)},deleteSessionContent:function(A,e){return p(A,[e],!0)},deleteSessionContents:function(A,e){return p(A,e,!1)},handleStartChat:w,handleErrorChat:v,reGenerateChat:function(A){if(s.value[A].role!==u.Ai)return;let e=s.value[A-1].content,i=s.value[A-1].cite;s.value.splice(A-1,s.value.length-A+1),L({message:e,cite:i})},reSendChat:function(A,{message:e,cite:i},t){s.value[A].role===u.User&&(s.value.splice(A,s.value.length-A),L({message:e,cite:i},t))},deleteChat:function(A){if(s.value[A].role===u.User){s.value.splice(A,2);return}s.value.splice(A-1,2)}}},S=({handleStart:A,handleEnd:e,handleError:i}={})=>{let t="",n=new f({handleStart:()=>(t="",null==A?void 0:A()),handleText:(A,e,i)=>{i||"正在思考..."===t?t=e:t+=e},handleEnd:()=>("无话可说"===t&&(t=""),null==e?void 0:e(t)),handleError:(A,e,t)=>null==i?void 0:i(e,t)});return{summary:({content:A,url:e,headers:i,model:t})=>{let o=m(z(A)),g=[{role:s.User,content:`你是一个总结大师,请帮助我对下面这段话进行总结。要求总结精炼,不超过 15 个字!且末尾没有标点符号!请注意:如果你无法总结,请回复“无话可说”!
|
247
247
|
文字如下:
|
248
248
|
${o}`}];n.stream({sessionCode:"summary",url:e,data:{prompts:g,model:t},headers:i})}}};I(86),I(84);let U=()=>{w(),v()},G=E.default;if("undefined"!=typeof window){let{currentScript:A}=window.document,e=A&&A.src.match(/(.+\/)[^/]+\.js(\?.*)?$/);e&&(I.p=e[1])}var R=D.eo,F=D.In,Z=D.c_,W=D.bJ,H=D.Ay,P=D.DA,J=D.Y_,X=D.a2,K=D.X3,_=D.S0;export{R as HttpErrorCode,F as SessionContentRole,Z as SessionContentStatus,W as SessionPromptRole,H as default,P as transferSessionContent2SessionPrompt,J as useChat,X as useClickProxy,K as useStyle,_ as useSummary};
|