Quellcode durchsuchen

Merge branch 'dev/second' of https://git.zyuas.com/LLM/chat-client-web into dev/second

S0025136190 vor 5 Monaten
Ursprung
Commit
e34dd28e48

+ 0 - 1
app/client/platforms/bigModel.ts

@@ -153,7 +153,6 @@ export class BigModelApi implements LLMApi {
             const chatMode = useChatStore.getState().chatMode;
             if (chatMode === 'LOCAL') {// 切片
               useChatStore.getState().updateCurrentSession((se) => {
-                console.log('update chat_id', info.id);
                 se.chat_id = info.id;
               });
               sliceInfoPromise = (async () => {

+ 34 - 1
app/client/platforms/deepSeek.ts

@@ -20,9 +20,9 @@ export class DeepSeekApi implements LLMApi {
   public apiPath: string;
 
   constructor() {
+    // this.baseURL = 'http://192.168.3.209:18078';
     this.baseURL = '/deepseek-api';
     this.apiPath = this.baseURL + '/vllm/ai/chat';
-    // this.apiPath = 'http://192.168.3.209:18078' + '/vllm/ai/chat';
   }
 
   async chat(options: ChatOptions) {
@@ -124,6 +124,7 @@ export class DeepSeekApi implements LLMApi {
       };
 
       controller.signal.onabort = finish;
+      let networkInfoPromise: Promise<void> | null = null;
 
       fetchEventSource(chatPath, {
         ...chatPayload,
@@ -164,8 +165,36 @@ export class DeepSeekApi implements LLMApi {
         onmessage: (msg) => {
           const info = JSON.parse(msg.data);
           if (info.event === 'finish') {
+            const isNetwork = useChatStore.getState().web_search;
+            if (isNetwork) {// 联网搜索结果
+              networkInfoPromise = (async () => {
+                try {
+                  const res: any = await api.get(`deepseek/api/web/search/${info.id}`);
+                  const networkInfo = {
+                    list: res.data.search_result,
+                  };
+                  useChatStore.getState().updateCurrentSession((session) => {
+                    session.messages = session.messages.map((item, index) => {
+                      if (index === session.messages.length - 1 && item.role !== 'user') {
+                        return {
+                          ...item,
+                          networkInfo: networkInfo,
+                        };
+                      } else {
+                        return {
+                          ...item,
+                        }
+                      }
+                    });
+                  });
+                } catch (error) {
+                  console.error(error);
+                }
+              })();
+            }
             return finish();
           }
+
           // 获取当前的数据
           const currentData = info.data;
           const formatStart = '```think';
@@ -181,6 +210,9 @@ export class DeepSeekApi implements LLMApi {
         },
         async onclose() {
           finish();
+          if (networkInfoPromise) {
+            await networkInfoPromise; // 等待 networkInfo 加载完成
+          }
           const session = useChatStore.getState().sessions[0];
           const item = session.messages.find(item => item.role === 'user');
           const dialogName = item ? item.content : '新的聊天';
@@ -195,6 +227,7 @@ export class DeepSeekApi implements LLMApi {
               role: item.role,
               content: item.content,
               document: item.document,
+              networkInfo: item.networkInfo,
             })),
           };
           await api.post('bigmodel/api/dialog/save', data);

+ 90 - 11
app/components/DeepSeekChat.tsx

@@ -22,10 +22,12 @@ import avatar from "../icons/aiIcon.png";
 import sdsk from "../icons/sdsk.png";
 import sdsk_selected from "../icons/sdsk_selected.png";
 import hlw from "../icons/hlw.png";
+import hlw_selected from "../icons/hlw_selected.png";
 import { Avatar } from "./emoji";
 import { MaskAvatar } from "./mask";
 
 import {
+  ChatMessage,
   SubmitKey,
   useChatStore,
   useAccessStore,
@@ -86,14 +88,15 @@ import { ExportMessageModal } from "./exporter";
 import { getClientConfig } from "../config/client";
 import { useAllModels } from "../utils/hooks";
 import { nanoid } from "nanoid";
-import { message, Upload, UploadProps, Tooltip } from "antd";
+import { message, Upload, UploadProps, Tooltip, Drawer, Button } from "antd";
 import {
   PaperClipOutlined,
   SendOutlined,
   FileOutlined,
   FilePdfOutlined,
   FileTextOutlined,
-  FileWordOutlined
+  FileWordOutlined,
+  RightOutlined
 } from '@ant-design/icons';
 
 export function createMessage(override: Partial<ChatMessage>): ChatMessage {
@@ -106,14 +109,6 @@ export function createMessage(override: Partial<ChatMessage>): ChatMessage {
   };
 }
 
-export type ChatMessage = RequestMessage & {
-  date: string;
-  streaming?: boolean;
-  isError?: boolean;
-  id: string;
-  model?: ModelType;
-};
-
 export const BOT_HELLO: ChatMessage = createMessage({
   role: "assistant",
   content: '您好,我是小智',
@@ -1373,6 +1368,68 @@ function _Chat() {
 
   const [webSearch, setWebSearch] = useState<boolean>(chatStore.web_search);
 
+  const [drawerOpen, setDrawerOpen] = useState(false);
+  type DrawerList = {
+    title: string,
+    content: string,
+    web_url: string,
+  }[]
+  const [drawerList, setDrawerList] = useState<DrawerList>([]);
+
+  interface NetworkDrawerProps {
+    list: DrawerList,
+  }
+
+  const NetworkDrawer: React.FC<NetworkDrawerProps> = (props) => {
+    return (
+      <Drawer
+        title='网页搜索'
+        open={drawerOpen}
+        onClose={() => {
+          setDrawerOpen(false);
+        }}
+      >
+        {props.list.map((item, index) => {
+          return <div
+            style={{
+              padding: 10,
+              background: '#fafafa',
+              borderRadius: 4,
+              marginBottom: 10,
+              cursor: 'pointer',
+            }}
+            key={index}
+            onClick={() => {
+              window.open(item.web_url);
+            }}
+          >
+            <div style={{
+              margin: '5px 0',
+              fontSize: 16,
+              display: '-webkit-box',
+              WebkitBoxOrient: 'vertical',
+              WebkitLineClamp: 2,// 限制显示两行
+              overflow: 'hidden',
+            }}>
+              {item.title}
+            </div>
+            <div style={{
+              color: '#afafaf',
+              display: '-webkit-box',
+              WebkitBoxOrient: 'vertical',
+              WebkitLineClamp: 4,// 限制显示两行
+              overflow: 'hidden',
+              textOverflow: 'ellipsis',
+            }}>
+              {item.content}
+            </div>
+          </div>
+        })
+        }
+      </Drawer >
+    )
+  }
+
   return (
     <div className={styles.chat} key={session.id}>
       {
@@ -1477,6 +1534,27 @@ function _Chat() {
                         正在输入…
                       </div>
                     )} */}
+                    {
+                      message.networkInfo && message.networkInfo.list.length > 0 &&
+                      <div style={{ marginTop: 10 }}>
+                        <Button
+                          icon={<RightOutlined />}
+                          iconPosition='end'
+                          onClick={() => {
+                            setDrawerList(message.networkInfo!.list);
+                            setDrawerOpen(true);
+                          }}
+                        >
+                          查询到{message.networkInfo.list.length}篇相关资料
+                        </Button>
+                        {
+                          drawerOpen &&
+                          <NetworkDrawer
+                            list={message.networkInfo.list}
+                          />
+                        }
+                      </div>
+                    }
                     <div className={styles["chat-message-item"]}>
                       <Markdown
                         key={message.streaming ? "loading" : "done"}
@@ -1689,7 +1767,7 @@ function _Chat() {
               }}
             >
               <img
-                src={hlw.src}
+                src={webSearch ? hlw_selected.src : hlw.src}
                 style={{
                   width: 18,
                   height: 18,
@@ -1836,6 +1914,7 @@ export function Chat() {
 
   useEffect(() => {
     chatStore.setModel('DeepSeek');
+    chatStore.setWebSearch(false);
   }, []);
 
   return <_Chat key={sessionIndex}></_Chat>;

+ 1 - 0
app/components/sidebar.tsx

@@ -433,6 +433,7 @@ export const SideBar = (props: { className?: string }) => {
                   content: item.content,
                   document: item.document ? item.document : undefined,
                   sliceInfo: item.sliceInfo ? item.sliceInfo : undefined,
+                  networkInfo: item.networkInfo ? item.networkInfo : undefined,
                 }
               }))
               const session = {

BIN
app/icons/hlw_selected.png


+ 4 - 1
app/store/chat.ts

@@ -42,7 +42,10 @@ export type ChatMessage = RequestMessage & {
   sliceInfo?: {
     knowledge_id: string,
     doc: any[],
-  }
+  },
+  networkInfo?: {
+    list: any[],
+  },
 };
 
 export function createMessage(override: Partial<ChatMessage>): ChatMessage {

+ 2 - 2
next.config.mjs

@@ -92,11 +92,11 @@ if (mode !== "export") {
       },
       {
         source: "/bigmodel-api/:path*",
-        destination: "http://xia0miduo.gicp.net:8401/:path*",
+        destination: "http://192.168.3.27:8091/:path*",
       },
       {
         source: "/deepseek-api/:path*",
-        destination: "http://10.1.27.6:11817/:path*",
+        destination: "http://192.168.3.209:18078/:path*",
       },
     ];