yt-chat-components 1.3.0 → 1.3.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/package.json +1 -1
- package/src/YtChatView/chatWidget/chatWindow/chatMessage/index.tsx +20 -3
- package/src/YtChatView/chatWidget/chatWindow/controllers/index.ts +1 -1
- package/src/YtChatView/chatWidget/chatWindow/index.tsx +29 -19
- package/src/YtChatView/chatWidget/index.tsx +6 -0
- package/src/YtChatView/chatWidget/style.js +16 -1
- package/src/YtChatView/mobileChat/index.jsx +4 -2
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,
|
|
@@ -314,7 +328,10 @@ export default function ChatMessage({
|
|
|
314
328
|
}
|
|
315
329
|
|
|
316
330
|
const resultItem: ThoughtChainItem = {
|
|
317
|
-
title:
|
|
331
|
+
title: <div style={{display:"flex", flexDirection: 'row', alignItems: 'center'}}>
|
|
332
|
+
{getAvatarByName(name)}
|
|
333
|
+
<span>{name}</span>
|
|
334
|
+
</div>,
|
|
318
335
|
description: toolCallInfo,
|
|
319
336
|
icon: getStatusIcon(status),
|
|
320
337
|
status: status,
|
|
@@ -355,7 +372,7 @@ export default function ChatMessage({
|
|
|
355
372
|
};
|
|
356
373
|
return resultItem
|
|
357
374
|
});
|
|
358
|
-
return <ThoughtChain items={items} />
|
|
375
|
+
return <ThoughtChain items={items} size={'small'} />
|
|
359
376
|
}
|
|
360
377
|
|
|
361
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
|
// 更新剩余缓冲区的起始位置
|
|
@@ -83,6 +83,8 @@ export default function ChatWindow({
|
|
|
83
83
|
modalWidth,
|
|
84
84
|
isMobile = false,
|
|
85
85
|
isShowChatHeader = true,
|
|
86
|
+
tipTitle,
|
|
87
|
+
tipContent,
|
|
86
88
|
}: {
|
|
87
89
|
is_enable_call:boolean;
|
|
88
90
|
tags: [];
|
|
@@ -127,6 +129,8 @@ export default function ChatWindow({
|
|
|
127
129
|
modalWidth: number;
|
|
128
130
|
isMobile: boolean;
|
|
129
131
|
isShowChatHeader: boolean;
|
|
132
|
+
tipTitle?: string;
|
|
133
|
+
tipContent?: string;
|
|
130
134
|
}) {
|
|
131
135
|
const ref = useRef<HTMLDivElement>(null);
|
|
132
136
|
const lastMessage = useRef<HTMLDivElement>(null);
|
|
@@ -195,7 +199,7 @@ export default function ChatWindow({
|
|
|
195
199
|
}
|
|
196
200
|
|
|
197
201
|
const addMessageItem = ({chunk, id, name, status = null, isThinkChunk = false, loadingMessage = null}) => {
|
|
198
|
-
// console.log("--- addMessageItem", chunk,
|
|
202
|
+
// console.log("--- addMessageItem", chunk, status, loadingMessage)
|
|
199
203
|
setNowAIContentList((prevState) => {
|
|
200
204
|
const content = {}
|
|
201
205
|
if(isThinkChunk){
|
|
@@ -220,7 +224,11 @@ export default function ChatWindow({
|
|
|
220
224
|
}
|
|
221
225
|
|
|
222
226
|
const updateMessageItem = ({chunk, status = null, isThinkChunk = false, loadingMessage = null}) => {
|
|
223
|
-
// console.log("--- updateMessageItem", chunk, status)
|
|
227
|
+
// console.log("--- updateMessageItem", chunk, status, loadingMessage)
|
|
228
|
+
// chunk 和 status 都为空,则不更新
|
|
229
|
+
if(isEmpty(chunk) && isEmpty(status)){
|
|
230
|
+
return
|
|
231
|
+
}
|
|
224
232
|
setNowAIContentList((prevState) => {
|
|
225
233
|
const latestMessageItem = prevState[prevState.length - 1]
|
|
226
234
|
const content = {}
|
|
@@ -251,7 +259,7 @@ export default function ChatWindow({
|
|
|
251
259
|
|
|
252
260
|
// 流式输出消息,实时显示(token为流式输出内容,end为结束输出,整体输出一次)
|
|
253
261
|
const handleMessageContent = (event, data) => {
|
|
254
|
-
console.log(
|
|
262
|
+
// console.log(`--- event = ${event}, content_ns = ${content_ns}, content_id = ${content_id}, data = `, data)
|
|
255
263
|
|
|
256
264
|
if (event == 'add_message' && data['sender'] == 'Machine') {
|
|
257
265
|
getHistoryList();
|
|
@@ -269,12 +277,12 @@ export default function ChatWindow({
|
|
|
269
277
|
// 如果刚才在调用工具,则追加信息
|
|
270
278
|
if (content_id === 'WAIT'){
|
|
271
279
|
content_id = id
|
|
272
|
-
updateMessageItem({chunk, loadingMessage: loading_message})
|
|
280
|
+
updateMessageItem({chunk, loadingMessage: loading_message || ''})
|
|
273
281
|
}
|
|
274
282
|
// 新建信息
|
|
275
283
|
else{
|
|
276
284
|
content_id = id
|
|
277
|
-
addMessageItem({chunk, id, name, loadingMessage:loading_message})
|
|
285
|
+
addMessageItem({chunk, id, name, loadingMessage: loading_message || ''})
|
|
278
286
|
}
|
|
279
287
|
}
|
|
280
288
|
// 输出主体没有变化
|
|
@@ -291,20 +299,18 @@ export default function ChatWindow({
|
|
|
291
299
|
|
|
292
300
|
// 如果 event_latest 是 token,此刻变成了 t_full_token,表示之前都在输出占位符,所以更新信息
|
|
293
301
|
if (event_latest === 'token' && event === 't_full_token'){
|
|
294
|
-
updateMessageItem({chunk, loadingMessage: loading_message})
|
|
302
|
+
updateMessageItem({chunk, loadingMessage: loading_message || ''})
|
|
295
303
|
} else {
|
|
296
304
|
addMessageItem({chunk, id, name, loadingMessage:loading_message})
|
|
297
305
|
}
|
|
298
306
|
}else{
|
|
299
|
-
updateMessageItem({chunk, loadingMessage: loading_message})
|
|
307
|
+
updateMessageItem({chunk, loadingMessage: loading_message || ''})
|
|
300
308
|
}
|
|
301
309
|
}
|
|
302
310
|
|
|
303
311
|
if (lastMessage.current) {
|
|
304
312
|
lastMessage.current.scrollIntoView({ behavior: 'smooth' });
|
|
305
313
|
}
|
|
306
|
-
|
|
307
|
-
|
|
308
314
|
}
|
|
309
315
|
else if (event == 't_token') {
|
|
310
316
|
let { chunk, id, r_id, ns, name, loading_message } = data
|
|
@@ -314,9 +320,9 @@ export default function ChatWindow({
|
|
|
314
320
|
content_ns = ns
|
|
315
321
|
// 新建信息
|
|
316
322
|
content_id = id
|
|
317
|
-
addMessageItem({chunk, id, name, status:null, isThinkChunk:true, loadingMessage: loading_message})
|
|
323
|
+
addMessageItem({chunk, id, name, status:null, isThinkChunk:true, loadingMessage: loading_message || ''})
|
|
318
324
|
}else {
|
|
319
|
-
updateMessageItem({chunk, status:null, isThinkChunk:true, loadingMessage: loading_message})
|
|
325
|
+
updateMessageItem({chunk, status:null, isThinkChunk:true, loadingMessage: loading_message || ''})
|
|
320
326
|
}
|
|
321
327
|
|
|
322
328
|
if (lastMessage.current) {
|
|
@@ -325,14 +331,14 @@ export default function ChatWindow({
|
|
|
325
331
|
}
|
|
326
332
|
else if (event == 'status') {
|
|
327
333
|
// 更新状态
|
|
328
|
-
const {r_id, id, ns, name, status} = data
|
|
334
|
+
const {r_id, id, ns, name, status, loading_message} = data
|
|
329
335
|
|
|
330
336
|
// ns变化表示切换了智能体,表示智能体一上来就调用工具
|
|
331
337
|
if (content_ns !== ns){
|
|
332
338
|
content_ns = ns
|
|
333
339
|
// 表示智能体连续调用工具
|
|
334
340
|
if (content_id === 'WAIT') {
|
|
335
|
-
updateMessageItem({chunk:"", status, loadingMessage: loading_message})
|
|
341
|
+
updateMessageItem({chunk:"", status, loadingMessage: loading_message || ''})
|
|
336
342
|
}else{
|
|
337
343
|
// 这个时候还没有信息的id,所以 content_id 给特殊值
|
|
338
344
|
content_id = "WAIT"
|
|
@@ -341,7 +347,7 @@ export default function ChatWindow({
|
|
|
341
347
|
}
|
|
342
348
|
// 当前智能体在调用工具
|
|
343
349
|
else{
|
|
344
|
-
updateMessageItem({chunk:"", status, loadingMessage: loading_message})
|
|
350
|
+
updateMessageItem({chunk:"", status, loadingMessage: loading_message || ''})
|
|
345
351
|
}
|
|
346
352
|
|
|
347
353
|
setAiStatus(data.status)
|
|
@@ -836,7 +842,7 @@ export default function ChatWindow({
|
|
|
836
842
|
*/
|
|
837
843
|
useEffect(() => {
|
|
838
844
|
if (lastMessage.current) lastMessage.current.scrollIntoView({ behavior: 'smooth' });
|
|
839
|
-
}, [
|
|
845
|
+
}, [nowAIContentList]);
|
|
840
846
|
|
|
841
847
|
/* Refocus the User input whenever a new response is returned from the LLM */
|
|
842
848
|
|
|
@@ -863,7 +869,7 @@ export default function ChatWindow({
|
|
|
863
869
|
let current_r_id: string = null
|
|
864
870
|
let current_sender: string = null
|
|
865
871
|
chatHistory.forEach((data) => {
|
|
866
|
-
const {sender, sender_name, text, id, category, r_id, error} = data;
|
|
872
|
+
const {sender, sender_name, text, id, category, r_id, error, reasoning_content} = data;
|
|
867
873
|
// r_id 不一样表示切换了对话轮次,则新增一个 ChatMessageType
|
|
868
874
|
if(current_r_id != r_id){
|
|
869
875
|
current_r_id = r_id
|
|
@@ -894,6 +900,7 @@ export default function ChatWindow({
|
|
|
894
900
|
id: id,
|
|
895
901
|
name: sender_name,
|
|
896
902
|
message: text,
|
|
903
|
+
thinkMessage: reasoning_content,
|
|
897
904
|
// rawInfo: data,
|
|
898
905
|
type: MessageType.text,
|
|
899
906
|
});
|
|
@@ -945,7 +952,10 @@ export default function ChatWindow({
|
|
|
945
952
|
return (
|
|
946
953
|
<div className={'cl-tips-wrapper'}>
|
|
947
954
|
<img className="drop-man-img" src={dropManUrl}/>
|
|
948
|
-
<div className="drop-down-title"
|
|
955
|
+
<div className="drop-down-title">
|
|
956
|
+
<strong>Hi,</strong><br/><strong>{tipTitle || `欢迎使用${window_title}!`}</strong><br/>
|
|
957
|
+
<div style={{fontSize:'14px'}}>{tipTitle || `您可以这样问我:`}</div>
|
|
958
|
+
</div>
|
|
949
959
|
<div className={'cl-drop-down-mobile'}>
|
|
950
960
|
<div className="drop-down-list-mobile">
|
|
951
961
|
{dropDownList.map(({backgroundImg, title}) => (
|
|
@@ -976,7 +986,7 @@ export default function ChatWindow({
|
|
|
976
986
|
if (isEmpty(dropManUrl)){
|
|
977
987
|
return (
|
|
978
988
|
<div className='cl-drop-down'>
|
|
979
|
-
<div className="drop-down-title">Hi
|
|
989
|
+
<div className="drop-down-title">Hi,{tipTitle || `欢迎使用${window_title}`},{tipContent || '您可以这样问我:'}</div>
|
|
980
990
|
<div className="drop-down-list">
|
|
981
991
|
{dropDownList.map(({backgroundImg, title}) => (
|
|
982
992
|
<div className="drop-down-item-card" key={title}>
|
|
@@ -1010,7 +1020,7 @@ export default function ChatWindow({
|
|
|
1010
1020
|
<div className={judgeDropClass()}>
|
|
1011
1021
|
<img className="drop-man-img" src={dropManUrl}/>
|
|
1012
1022
|
<div className='cl-drop-down'>
|
|
1013
|
-
<div className="drop-down-title">Hi
|
|
1023
|
+
<div className="drop-down-title">Hi,{tipTitle || `欢迎使用${window_title}`},{tipContent || '您可以这样问我:'}</div>
|
|
1014
1024
|
<div className="drop-down-list">
|
|
1015
1025
|
{dropDownList.map(({backgroundImg, title}) => (
|
|
1016
1026
|
<div
|
|
@@ -45,6 +45,8 @@ export default function ChatWidget({
|
|
|
45
45
|
modalWidth,
|
|
46
46
|
isMobile = false,
|
|
47
47
|
isShowChatHeader = true,
|
|
48
|
+
tipTitle,
|
|
49
|
+
tipContent,
|
|
48
50
|
}: {
|
|
49
51
|
is_enable_call:boolean,
|
|
50
52
|
tags: [];
|
|
@@ -85,6 +87,8 @@ export default function ChatWidget({
|
|
|
85
87
|
modalWidth: number;
|
|
86
88
|
isMobile: boolean;
|
|
87
89
|
isShowChatHeader: boolean;
|
|
90
|
+
tipTitle: string,
|
|
91
|
+
tipContent: string,
|
|
88
92
|
}) {
|
|
89
93
|
const [open, setOpen] = useState(start_open);
|
|
90
94
|
const [messages, setMessages] = useState<ChatMessageType[]>([]);
|
|
@@ -157,6 +161,8 @@ export default function ChatWidget({
|
|
|
157
161
|
modalWidth={modalWidth}
|
|
158
162
|
isMobile={isMobile}
|
|
159
163
|
isShowChatHeader={isShowChatHeader}
|
|
164
|
+
tipTitle={tipTitle}
|
|
165
|
+
tipContent={tipContent}
|
|
160
166
|
/>
|
|
161
167
|
</div>
|
|
162
168
|
);
|
|
@@ -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
|
+
`
|
|
@@ -382,8 +382,6 @@ export class MobileChatPage extends React.Component {
|
|
|
382
382
|
|
|
383
383
|
setWindowTitle = (title) => {
|
|
384
384
|
if (!isEmpty(title)){
|
|
385
|
-
document.title = 'AI校园智多星';
|
|
386
|
-
window.document.title = 'AI校园智多星';
|
|
387
385
|
}
|
|
388
386
|
}
|
|
389
387
|
|
|
@@ -499,6 +497,8 @@ export class MobileChatPage extends React.Component {
|
|
|
499
497
|
isLogin = false,
|
|
500
498
|
isShowLogin = false,
|
|
501
499
|
loginBtnClick,
|
|
500
|
+
tipTitle,
|
|
501
|
+
tipContent
|
|
502
502
|
} = this.props;
|
|
503
503
|
const { sceneInfo, currentFlow = {} } = this.state;
|
|
504
504
|
const { flows = [], name: sceneName, character } = sceneInfo;
|
|
@@ -771,6 +771,8 @@ export class MobileChatPage extends React.Component {
|
|
|
771
771
|
modalWidth={modalWidth}
|
|
772
772
|
isMobile={true}
|
|
773
773
|
isShowChatHeader={false}
|
|
774
|
+
tipTitle={tipTitle}
|
|
775
|
+
tipContent={tipContent}
|
|
774
776
|
/>
|
|
775
777
|
</div>
|
|
776
778
|
{
|