Skip to content

Commit

Permalink
fix: fix the stream handler of the lui (#166)
Browse files Browse the repository at this point in the history
* 优化client stream流格式处理
* 对话框雕花,修复markdown气泡样式不统一问题
* release [email protected]
  • Loading branch information
xingwanying authored Jun 25, 2024
2 parents 9b410ce + a94efaa commit 0807966
Show file tree
Hide file tree
Showing 8 changed files with 72 additions and 72 deletions.
5 changes: 5 additions & 0 deletions client/app/factory/edit/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,10 @@ export default function Edit({ params }: { params: { id: string } }) {
'https://mdn.alipayobjects.com/huamei_j8gzmo/afts/img/A*YAP3SI7MMHQAAAAAAAAAAAAADrPSAQ/original',
title: 'PeterCat',
}}
style={{
backgroundColor: '#fff',
}}
hideLogo={true}
apiUrl="/api/chat/stream_builder"
apiDomain={API_HOST}
helloMessage="👋🏻 你好,我是 Peter Cat, 初次见面,先自我介绍一下:我是一个开源项目的机器人。你可以通过和我对话配置一个答疑机器人。"
Expand Down Expand Up @@ -323,6 +327,7 @@ export default function Edit({ params }: { params: { id: string } }) {
<div style={{ height: 'calc(100vh - 73px)' }}>
{isEdit && (
<Chat
hideLogo={true}
assistantMeta={{
avatar:
botProfile?.avatar ||
Expand Down
2 changes: 1 addition & 1 deletion client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"lottie-react": "^2.4.0",
"next": "14.0.1",
"openai": "^4.24.7",
"petercat-lui": "^0.0.18",
"petercat-lui": "^0.0.19",
"postcss": "8.4.27",
"react": "18.2.0",
"react-dom": "18.2.0",
Expand Down
8 changes: 4 additions & 4 deletions client/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -11252,10 +11252,10 @@ pbkdf2@^3.0.3, pbkdf2@^3.1.2:
safe-buffer "^5.0.1"
sha.js "^2.4.8"

petercat-lui@^0.0.18:
version "0.0.18"
resolved "https://registry.npmjs.org/petercat-lui/-/petercat-lui-0.0.18.tgz#26d8a0d3c8bc44a6032ee17a8923fca7d3bfef81"
integrity sha512-oUi2ZvsnpiDVchmtvQ4HGn4eERec8VkbsO4Z+iEW/XC1OCMhjfntM3fbQTZOvCwLqlPkuCUNUIP3QHi0IlLDhA==
petercat-lui@^0.0.19:
version "0.0.19"
resolved "https://registry.npmjs.org/petercat-lui/-/petercat-lui-0.0.19.tgz#2f9e97de66aa7a8e0e86324169d89e3008d5adfb"
integrity sha512-8luZDTLKUs/BUeZGCRQ9MfKAxod1GOEsOI6T+Ta4R8b2t/hYLsjeAmQLGrmfIneq8TAZHfraQfsZQmqABGu01g==
dependencies:
"@ant-design/icons" "^5.3.5"
"@ant-design/pro-chat" "^1.9.0"
Expand Down
2 changes: 1 addition & 1 deletion lui/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "petercat-lui",
"version": "0.0.18",
"version": "0.0.19",
"description": "A react library developed with dumi",
"module": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down
1 change: 1 addition & 0 deletions lui/src/Chat/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export default () => (
<div style={{ height: '100vh' }}>
<Chat
apiUrl="/api/chat/stream_builder"
hideLogo="true"
/>
</div>
);
Expand Down
81 changes: 45 additions & 36 deletions lui/src/Chat/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type {
import { ProChat } from '@ant-design/pro-chat';
import { Markdown } from '@ant-design/pro-editor';

import { includes, isEmpty, map } from 'lodash';
import { isEmpty, map } from 'lodash';
import React, {
ReactNode,
memo,
Expand Down Expand Up @@ -42,6 +42,7 @@ export interface ChatProps extends BotInfo {
prompt?: string;
token?: string;
style?: React.CSSProperties;
hideLogo?: boolean;
}

const Chat: FC<ChatProps> = memo(
Expand All @@ -55,6 +56,7 @@ const Chat: FC<ChatProps> = memo(
prompt,
token,
style,
hideLogo = false,
}) => {
const proChatRef = useRef<ProChatInstance>();
const [chats, setChats] = useState<ChatMessage<Record<string, any>>[]>();
Expand Down Expand Up @@ -119,7 +121,7 @@ const Chat: FC<ChatProps> = memo(
}}
>
<div className="h-full w-full flex flex-col">
<SignatureIcon className="mx-auto my-2 flex-none" />
{!hideLogo && <SignatureIcon className="mx-auto my-2 flex-none" />}
<ProChat
className="flex-1"
showTitle
Expand Down Expand Up @@ -147,7 +149,10 @@ const Chat: FC<ChatProps> = memo(
if (originData?.role === Role.user) {
return defaultDom;
}
const message = originData.content;

const originMessage = convertChunkToJson(
originData.content,
) as any;

const defaultMessageContent = (
<div
Expand All @@ -158,55 +163,57 @@ const Chat: FC<ChatProps> = memo(
</div>
);

if (!message || !includes(message, '<TOOL>')) {
return defaultMessageContent;
}

const [toolStr, answerStr] = message.split('<ANSWER>');
const tools = toolStr.split('\n').filter(Boolean);
const lastTool = tools[tools.length - 1];

const regex = /<TOOL>(.*)/;
const match = lastTool.match(regex);

if (!match) {
console.error('No valid JSON found in input');
if (!originMessage || typeof originMessage === 'string') {
return defaultMessageContent;
}

try {
const config = JSON.parse(match[1]);
const { type, extra } = config;

if (![Role.knowledge, Role.tool].includes(type)) {
return defaultMessageContent;
}

const { status, source } = extra;
const { message: answerStr, tools = [] } = originMessage;

if (isEmpty(tools)) {
return (
<div
className="p-2 bg-white rounded-md "
className="leftMessageContent"
style={{ minWidth: messageMinWidth }}
>
<div className="mb-1">
<ThoughtChain
content={extra}
status={status}
source={source}
/>
</div>
<Markdown
className="ant-pro-chat-list-item-message-content"
style={{ overflowX: 'hidden', overflowY: 'auto' }}
>
{answerStr}
</Markdown>
</div>
);
} catch (error) {
console.error(`JSON parse error: ${error}`);
}

const lastTool = tools[tools.length - 1];
const { type, extra } = lastTool;

if (![Role.knowledge, Role.tool].includes(type)) {
return defaultMessageContent;
}

const { status, source } = extra;

return (
<div
className="leftMessageContent"
style={{ minWidth: messageMinWidth }}
>
<div className="mb-1">
<ThoughtChain
content={extra}
status={status}
source={source}
/>
</div>
<Markdown
className="ant-pro-chat-list-item-message-content"
style={{ overflowX: 'hidden', overflowY: 'auto' }}
>
{answerStr}
</Markdown>
</div>
);
},
}}
assistantMeta={{
Expand All @@ -233,7 +240,9 @@ const Chat: FC<ChatProps> = memo(
)
.map((message) => ({
role: message.role,
content: message.content as string,
content: JSON.stringify(
convertChunkToJson(message.content as string),
),
}));

const response = await streamChat(
Expand Down
35 changes: 13 additions & 22 deletions lui/src/utils/chatTranslator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,33 +9,24 @@ interface Tool {
};
}

interface Message {
type: string;
content: string;
role: string;
}

export const convertChunkToJson = (rawData: string) => {
const chunks = rawData?.trim()?.split('\n\n');
const tools: Tool[] = [];
const messages: string[] = [];

forEach(chunks, (chunk) => {
const parsedChunk = JSON.parse(chunk);
if (parsedChunk.type === 'tool') {
tools.push(parsedChunk);
} else if (parsedChunk.type === 'message') {
messages.push(parsedChunk.content);
}
});

const combinedMessage: Message = {
type: 'message',
content: messages.join(''),
role: 'assistant',
};

return JSON.stringify([...tools, combinedMessage]);
try {
forEach(chunks, (chunk) => {
const parsedChunk = JSON.parse(chunk);
if (parsedChunk.type === 'tool') {
tools.push(parsedChunk);
} else if (parsedChunk.type === 'message') {
messages.push(parsedChunk.content);
}
});
return { tools, message: messages.join('') };
} catch (error) {
return rawData;
}
};

export const handleStream = async (response: Response) => {
Expand Down
10 changes: 2 additions & 8 deletions server/agent/base.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import json
from typing import AsyncIterator, Dict, Callable, Optional
import uuid
# import uuid
from langchain.agents import AgentExecutor
from data_class import ChatData, Message
from langchain.agents.format_scratchpad.openai_tools import (
Expand Down Expand Up @@ -144,22 +144,18 @@ async def run_stream_chat(self, input_data: ChatData) -> AsyncIterator[str]:
f"with output: {event['data'].get('output')['output']}"
)
if kind == "on_chat_model_stream":
id = str(uuid.uuid4())
# id = str(uuid.uuid4())
content = event["data"]["chunk"].content
if content:
json_output = json.dumps({
"id": id,
"type": "message",
"content": content,
"role": "assistant",
}, ensure_ascii=False)
yield f"{json_output}\n\n"
elif kind == "on_tool_start":
children_value = event["data"].get("input", {})
json_output = json.dumps({
"type": "tool",
"role": "tool",
"id": id,
"extra": {
"source": f"已调用工具: {event['name']}",
"pluginName": "GitHub",
Expand All @@ -173,8 +169,6 @@ async def run_stream_chat(self, input_data: ChatData) -> AsyncIterator[str]:
children_value = event["data"].get("output", {})
json_output = json.dumps({
"type": "tool",
"role": "tool",
"id": id,
"extra": {
"source": f"已调用工具: {event['name']}",
"pluginName": "GitHub",
Expand Down

0 comments on commit 0807966

Please sign in to comment.