yt-chat-components 1.2.9 → 1.3.1
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/package.json +1 -1
- package/src/YtChatView/chatWidget/chatWindow/chatMessage/index.tsx +26 -7
- package/src/YtChatView/chatWidget/chatWindow/controllers/index.ts +1 -1
- package/src/YtChatView/chatWidget/chatWindow/index.tsx +40 -22
- package/src/YtChatView/chatWidget/chatWindow/types/chatWidget/index.ts +1 -0
- package/src/YtChatView/chatWidget/style.js +16 -1
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@ import remarkGfm from 'remark-gfm';
|
|
|
6
6
|
import rehypeMathjax from 'rehype-mathjax';
|
|
7
7
|
// import './index.module.css';
|
|
8
8
|
import upFilePng from '../../../../assets/aicenter/upfile.png';
|
|
9
|
-
import {Button, Collapse, DatePicker, Form, Image, Input, message as messageTip, Select, Skeleton} from 'antd';
|
|
9
|
+
import {Button, Collapse, DatePicker, Form, Image, Input, message as messageTip, Select, Skeleton, Avatar} from 'antd';
|
|
10
10
|
import React, {useRef, useState} from 'react';
|
|
11
11
|
import typePdfPng from '../../../../assets/aicenter/type-pdf.png';
|
|
12
12
|
import typeWordPng from '../../../../assets/aicenter/type-word.png';
|
|
@@ -30,6 +30,20 @@ const isEmpty = (o) => {
|
|
|
30
30
|
return !o || (typeof o === 'object' && Object.keys(o).length === 0) || (typeof o === 'string' && o.trim().length === 0);
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
// 使用 for 循环生成头像图片数组
|
|
34
|
+
const avatarImages = [];
|
|
35
|
+
for (let i = 1; i <= 68; i++) {
|
|
36
|
+
avatarImages.push(`https://ai-file.yuntu.cn/yt-ai/system/${i}.png`);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// 根据name生成固定的颜色索引
|
|
40
|
+
const getAvatarByName = (name: string) => {
|
|
41
|
+
const total = name.split('').reduce((acc, char) => acc + char.charCodeAt(0), 0);
|
|
42
|
+
const index = total % avatarImages.length;
|
|
43
|
+
const img = avatarImages[index];
|
|
44
|
+
return <Avatar shape="square" src={img} style={{marginRight: 8}}/>
|
|
45
|
+
};
|
|
46
|
+
|
|
33
47
|
export default function ChatMessage({
|
|
34
48
|
receivingMessage,
|
|
35
49
|
setReceivingMessage,
|
|
@@ -302,18 +316,22 @@ export default function ChatMessage({
|
|
|
302
316
|
|
|
303
317
|
const renderBotTextMessage = () => {
|
|
304
318
|
const items = messageItemList.map((item, index) => {
|
|
305
|
-
const {id, thinkMessage, message, type, name, toolCallInfo, rawInfo} = item;
|
|
319
|
+
const {id, thinkMessage, message, loadingMessage, type, name, toolCallInfo, rawInfo} = item;
|
|
320
|
+
const isLatest = index == messageItemList.length - 1;
|
|
306
321
|
let status = 'success'
|
|
307
322
|
// 只有在接收信息的时候有 pending 状态
|
|
308
323
|
if (receivingMessage && isLatest){
|
|
309
324
|
// 最后的信息才为 pending
|
|
310
|
-
if(
|
|
325
|
+
if(isLatest){
|
|
311
326
|
status = 'pending'
|
|
312
327
|
}
|
|
313
328
|
}
|
|
314
329
|
|
|
315
330
|
const resultItem: ThoughtChainItem = {
|
|
316
|
-
title:
|
|
331
|
+
title: <div style={{display:"flex", flexDirection: 'row', alignItems: 'center'}}>
|
|
332
|
+
{getAvatarByName(name)}
|
|
333
|
+
<span>{name}</span>
|
|
334
|
+
</div>,
|
|
317
335
|
description: toolCallInfo,
|
|
318
336
|
icon: getStatusIcon(status),
|
|
319
337
|
status: status,
|
|
@@ -325,7 +343,7 @@ export default function ChatMessage({
|
|
|
325
343
|
size="small"
|
|
326
344
|
defaultActiveKey={'1'}
|
|
327
345
|
expandIconPosition={'end'}
|
|
328
|
-
items={[{key: '1', label: renderThinkTitle(isEmpty(message)), children: <Markdown
|
|
346
|
+
items={[{key: '1', label: renderThinkTitle(isEmpty(message) && isLatest), children: <Markdown
|
|
329
347
|
className={'think markdown-body prose flex flex-col word-break-break-word'}
|
|
330
348
|
remarkPlugins={[remarkGfm]}
|
|
331
349
|
rehypePlugins={[rehypeMathjax]}
|
|
@@ -334,6 +352,7 @@ export default function ChatMessage({
|
|
|
334
352
|
</Markdown>}]}
|
|
335
353
|
/>
|
|
336
354
|
}
|
|
355
|
+
{/* 有 thinkMessage 的时候没有占位符,否则赞为符输出*/}
|
|
337
356
|
{
|
|
338
357
|
message ? <Markdown
|
|
339
358
|
key={id}
|
|
@@ -343,7 +362,7 @@ export default function ChatMessage({
|
|
|
343
362
|
components={CustomRender}
|
|
344
363
|
>
|
|
345
364
|
{message}
|
|
346
|
-
</Markdown> : thinkMessage ? "" : <ChatMessagePlaceholderInThought aiStatus={"正在处理数据"} />
|
|
365
|
+
</Markdown> : thinkMessage ? "" : <ChatMessagePlaceholderInThought aiStatus={loadingMessage ? loadingMessage : "正在处理数据"} />
|
|
347
366
|
}
|
|
348
367
|
</div>,
|
|
349
368
|
footer: <div key={id} className="msg_operateBox">
|
|
@@ -353,7 +372,7 @@ export default function ChatMessage({
|
|
|
353
372
|
};
|
|
354
373
|
return resultItem
|
|
355
374
|
});
|
|
356
|
-
return <ThoughtChain items={items} />
|
|
375
|
+
return <ThoughtChain items={items} size={'small'} />
|
|
357
376
|
}
|
|
358
377
|
|
|
359
378
|
const renderBotFormMessage = (form_config) => {
|
|
@@ -163,7 +163,7 @@ const extractAndParseJSON = (buffer, handleMessageContent) => {
|
|
|
163
163
|
handleMessageContent(parsedJson['event'], parsedJson['data']);
|
|
164
164
|
parsedData.push(parsedJson); // 添加到解析结果中
|
|
165
165
|
} catch (error) {
|
|
166
|
-
console.warn('无法解析 JSON 数据:', error);
|
|
166
|
+
console.warn('无法解析 JSON 数据:', error, jsonString);
|
|
167
167
|
}
|
|
168
168
|
|
|
169
169
|
// 更新剩余缓冲区的起始位置
|
|
@@ -150,6 +150,7 @@ export default function ChatWindow({
|
|
|
150
150
|
const [inputContainerHeight, setInputContainerHeight] = useState('50px')
|
|
151
151
|
let content_id: string = null
|
|
152
152
|
let content_ns: string = null
|
|
153
|
+
let event_latest: string = null
|
|
153
154
|
const nowAIContentListRef = useRef(nowAIContentList)
|
|
154
155
|
|
|
155
156
|
let voiceChunks = []; // 临时存储录制的语音片段
|
|
@@ -176,7 +177,7 @@ export default function ChatWindow({
|
|
|
176
177
|
if (delayMessageList.length > 0) {
|
|
177
178
|
const data = delayMessageList.shift();
|
|
178
179
|
const {r_id, form_config} = data;
|
|
179
|
-
updateMessageItem("\n```form\n" + JSON.stringify(form_config) + "\n```\n")
|
|
180
|
+
updateMessageItem({chunk:"\n```form\n" + JSON.stringify(form_config) + "\n```\n"})
|
|
180
181
|
|
|
181
182
|
// ?????? done
|
|
182
183
|
// addMessage({
|
|
@@ -193,8 +194,8 @@ export default function ChatWindow({
|
|
|
193
194
|
}
|
|
194
195
|
}
|
|
195
196
|
|
|
196
|
-
const addMessageItem = (chunk, id, name, status = null, isThinkChunk = false) => {
|
|
197
|
-
// console.log("--- addMessageItem", chunk,
|
|
197
|
+
const addMessageItem = ({chunk, id, name, status = null, isThinkChunk = false, loadingMessage = null}) => {
|
|
198
|
+
// console.log("--- addMessageItem", chunk, status, loadingMessage)
|
|
198
199
|
setNowAIContentList((prevState) => {
|
|
199
200
|
const content = {}
|
|
200
201
|
if(isThinkChunk){
|
|
@@ -210,6 +211,7 @@ export default function ChatWindow({
|
|
|
210
211
|
name,
|
|
211
212
|
type: MessageType.text,
|
|
212
213
|
toolCallInfo: status,
|
|
214
|
+
loadingMessage,
|
|
213
215
|
...content
|
|
214
216
|
}
|
|
215
217
|
nowAIContentListRef.current = [...prevState, messageItem]
|
|
@@ -217,8 +219,12 @@ export default function ChatWindow({
|
|
|
217
219
|
})
|
|
218
220
|
}
|
|
219
221
|
|
|
220
|
-
const updateMessageItem = (chunk, status = null, isThinkChunk = false) => {
|
|
221
|
-
// console.log("--- updateMessageItem", chunk, status)
|
|
222
|
+
const updateMessageItem = ({chunk, status = null, isThinkChunk = false, loadingMessage = null}) => {
|
|
223
|
+
// console.log("--- updateMessageItem", chunk, status, loadingMessage)
|
|
224
|
+
// chunk 和 status 都为空,则不更新
|
|
225
|
+
if(isEmpty(chunk) && isEmpty(status)){
|
|
226
|
+
return
|
|
227
|
+
}
|
|
222
228
|
setNowAIContentList((prevState) => {
|
|
223
229
|
const latestMessageItem = prevState[prevState.length - 1]
|
|
224
230
|
const content = {}
|
|
@@ -235,6 +241,7 @@ export default function ChatWindow({
|
|
|
235
241
|
name: latestMessageItem.name,
|
|
236
242
|
type: latestMessageItem.type,
|
|
237
243
|
toolCallInfo: status,
|
|
244
|
+
loadingMessage,
|
|
238
245
|
...content
|
|
239
246
|
}
|
|
240
247
|
|
|
@@ -248,13 +255,13 @@ export default function ChatWindow({
|
|
|
248
255
|
|
|
249
256
|
// 流式输出消息,实时显示(token为流式输出内容,end为结束输出,整体输出一次)
|
|
250
257
|
const handleMessageContent = (event, data) => {
|
|
251
|
-
// console.log(
|
|
258
|
+
// console.log(`--- event = ${event}, content_ns = ${content_ns}, content_id = ${content_id}, data = `, data)
|
|
252
259
|
|
|
253
260
|
if (event == 'add_message' && data['sender'] == 'Machine') {
|
|
254
261
|
getHistoryList();
|
|
255
262
|
}
|
|
256
|
-
else if (event == 'token') {
|
|
257
|
-
let { chunk, id, r_id, ns, name } = data
|
|
263
|
+
else if (event == 'token' || event == 't_full_token') {
|
|
264
|
+
let { chunk, id, r_id, ns, name, loading_message } = data
|
|
258
265
|
if (chunk.includes('```') && !chunk.startsWith('\n')) {
|
|
259
266
|
// 确保 ``` 前有换行
|
|
260
267
|
chunk = '\n' + chunk;
|
|
@@ -266,14 +273,16 @@ export default function ChatWindow({
|
|
|
266
273
|
// 如果刚才在调用工具,则追加信息
|
|
267
274
|
if (content_id === 'WAIT'){
|
|
268
275
|
content_id = id
|
|
269
|
-
updateMessageItem(chunk)
|
|
276
|
+
updateMessageItem({chunk, loadingMessage: loading_message || ''})
|
|
270
277
|
}
|
|
271
278
|
// 新建信息
|
|
272
279
|
else{
|
|
273
280
|
content_id = id
|
|
274
|
-
addMessageItem(chunk, id, name)
|
|
281
|
+
addMessageItem({chunk, id, name, loadingMessage: loading_message || ''})
|
|
275
282
|
}
|
|
276
|
-
}
|
|
283
|
+
}
|
|
284
|
+
// 输出主体没有变化
|
|
285
|
+
else {
|
|
277
286
|
// 如果 content_id === WAIT 表示 token 发出来之前 agent在调用工具
|
|
278
287
|
// 但是调用工具的时候已经创建了信息,所以这里更新一下 content_id。这样就可以追加信息
|
|
279
288
|
if(content_id === 'WAIT'){
|
|
@@ -283,9 +292,15 @@ export default function ChatWindow({
|
|
|
283
292
|
// id切换表示一句话说完了, 新增信息
|
|
284
293
|
if (content_id !== id){
|
|
285
294
|
content_id = id
|
|
286
|
-
|
|
295
|
+
|
|
296
|
+
// 如果 event_latest 是 token,此刻变成了 t_full_token,表示之前都在输出占位符,所以更新信息
|
|
297
|
+
if (event_latest === 'token' && event === 't_full_token'){
|
|
298
|
+
updateMessageItem({chunk, loadingMessage: loading_message || ''})
|
|
299
|
+
} else {
|
|
300
|
+
addMessageItem({chunk, id, name, loadingMessage:loading_message})
|
|
301
|
+
}
|
|
287
302
|
}else{
|
|
288
|
-
updateMessageItem(chunk)
|
|
303
|
+
updateMessageItem({chunk, loadingMessage: loading_message || ''})
|
|
289
304
|
}
|
|
290
305
|
}
|
|
291
306
|
|
|
@@ -294,16 +309,16 @@ export default function ChatWindow({
|
|
|
294
309
|
}
|
|
295
310
|
}
|
|
296
311
|
else if (event == 't_token') {
|
|
297
|
-
let { chunk, id, r_id, ns, name } = data
|
|
312
|
+
let { chunk, id, r_id, ns, name, loading_message } = data
|
|
298
313
|
|
|
299
314
|
// ns切换表示切换了智能体
|
|
300
315
|
if (content_ns !== ns){
|
|
301
316
|
content_ns = ns
|
|
302
317
|
// 新建信息
|
|
303
318
|
content_id = id
|
|
304
|
-
addMessageItem(chunk, id, name, null, true)
|
|
319
|
+
addMessageItem({chunk, id, name, status:null, isThinkChunk:true, loadingMessage: loading_message || ''})
|
|
305
320
|
}else {
|
|
306
|
-
updateMessageItem(chunk, null, true)
|
|
321
|
+
updateMessageItem({chunk, status:null, isThinkChunk:true, loadingMessage: loading_message || ''})
|
|
307
322
|
}
|
|
308
323
|
|
|
309
324
|
if (lastMessage.current) {
|
|
@@ -312,23 +327,23 @@ export default function ChatWindow({
|
|
|
312
327
|
}
|
|
313
328
|
else if (event == 'status') {
|
|
314
329
|
// 更新状态
|
|
315
|
-
const {r_id, id, ns, name, status} = data
|
|
330
|
+
const {r_id, id, ns, name, status, loading_message} = data
|
|
316
331
|
|
|
317
332
|
// ns变化表示切换了智能体,表示智能体一上来就调用工具
|
|
318
333
|
if (content_ns !== ns){
|
|
319
334
|
content_ns = ns
|
|
320
335
|
// 表示智能体连续调用工具
|
|
321
336
|
if (content_id === 'WAIT') {
|
|
322
|
-
updateMessageItem("", status)
|
|
337
|
+
updateMessageItem({chunk:"", status, loadingMessage: loading_message || ''})
|
|
323
338
|
}else{
|
|
324
339
|
// 这个时候还没有信息的id,所以 content_id 给特殊值
|
|
325
340
|
content_id = "WAIT"
|
|
326
|
-
addMessageItem("", "WAIT", name, status)
|
|
341
|
+
addMessageItem({chunk:"", id: "WAIT", name, status})
|
|
327
342
|
}
|
|
328
343
|
}
|
|
329
344
|
// 当前智能体在调用工具
|
|
330
345
|
else{
|
|
331
|
-
updateMessageItem("", status)
|
|
346
|
+
updateMessageItem({chunk:"", status, loadingMessage: loading_message || ''})
|
|
332
347
|
}
|
|
333
348
|
|
|
334
349
|
setAiStatus(data.status)
|
|
@@ -410,6 +425,8 @@ export default function ChatWindow({
|
|
|
410
425
|
content_ns = null
|
|
411
426
|
content_id = null
|
|
412
427
|
}
|
|
428
|
+
|
|
429
|
+
event_latest = event
|
|
413
430
|
};
|
|
414
431
|
|
|
415
432
|
const sendMessageNoStream = (res) => {
|
|
@@ -821,7 +838,7 @@ export default function ChatWindow({
|
|
|
821
838
|
*/
|
|
822
839
|
useEffect(() => {
|
|
823
840
|
if (lastMessage.current) lastMessage.current.scrollIntoView({ behavior: 'smooth' });
|
|
824
|
-
}, [
|
|
841
|
+
}, [nowAIContentList]);
|
|
825
842
|
|
|
826
843
|
/* Refocus the User input whenever a new response is returned from the LLM */
|
|
827
844
|
|
|
@@ -848,7 +865,7 @@ export default function ChatWindow({
|
|
|
848
865
|
let current_r_id: string = null
|
|
849
866
|
let current_sender: string = null
|
|
850
867
|
chatHistory.forEach((data) => {
|
|
851
|
-
const {sender, sender_name, text, id, category, r_id, error} = data;
|
|
868
|
+
const {sender, sender_name, text, id, category, r_id, error, reasoning_content} = data;
|
|
852
869
|
// r_id 不一样表示切换了对话轮次,则新增一个 ChatMessageType
|
|
853
870
|
if(current_r_id != r_id){
|
|
854
871
|
current_r_id = r_id
|
|
@@ -879,6 +896,7 @@ export default function ChatWindow({
|
|
|
879
896
|
id: id,
|
|
880
897
|
name: sender_name,
|
|
881
898
|
message: text,
|
|
899
|
+
thinkMessage: reasoning_content,
|
|
882
900
|
// rawInfo: data,
|
|
883
901
|
type: MessageType.text,
|
|
884
902
|
});
|
|
@@ -2459,5 +2459,20 @@ export const yt_style = `
|
|
|
2459
2459
|
background: #1552FF;
|
|
2460
2460
|
border-radius: 8px;
|
|
2461
2461
|
}
|
|
2462
|
-
`
|
|
2463
2462
|
|
|
2463
|
+
.ant-thought-chain-item-title{
|
|
2464
|
+
max-height: 32px !important;
|
|
2465
|
+
height: 32px !important;
|
|
2466
|
+
}
|
|
2467
|
+
|
|
2468
|
+
.ant-thought-chain-item-icon{
|
|
2469
|
+
margin-top: 6px !important;
|
|
2470
|
+
}
|
|
2471
|
+
|
|
2472
|
+
.ant-thought-chain-item-header::before {
|
|
2473
|
+
top: 6px !important;
|
|
2474
|
+
}
|
|
2475
|
+
.ant-thought-chain-item-content::before {
|
|
2476
|
+
height: 55px !important;
|
|
2477
|
+
}
|
|
2478
|
+
`
|