李富豪 6 ماه پیش
والد
کامیت
229bb94a71
3فایلهای تغییر یافته به همراه192 افزوده شده و 24 حذف شده
  1. 12 12
      app/components/DeekSeekHome.tsx
  2. 179 5
      app/components/chat.tsx
  3. 1 7
      app/components/sidebar.tsx

+ 12 - 12
app/components/DeekSeekHome.tsx

@@ -20,18 +20,18 @@ const DeekSeek: React.FC = () => {
     React.useEffect(() => {
         chatStore.clearSessions();
         setList([
-            {
-                title: '智能问答',
-                onClick: () => {
-                    navigate({ pathname: '/deepseekChat' })
-                }
-            },
-            {
-                title: '知识库问答',
-                onClick: () => {
-                    navigate({ pathname: '/knowledgeChat' })
-                }
-            },
+            // {
+            //     title: '智能问答',
+            //     onClick: () => {
+            //         navigate({ pathname: '/deepseekChat' })
+            //     }
+            // },
+            // {
+            //     title: '知识库问答',
+            //     onClick: () => {
+            //         navigate({ pathname: '/knowledgeChat' })
+            //     }
+            // },
             {
                 title: '数字系统答疑',
                 onClick: () => {

+ 179 - 5
app/components/chat.tsx

@@ -109,8 +109,14 @@ import { prettyObject } from "../utils/format";
 import { ExportMessageModal } from "./exporter";
 import { getClientConfig } from "../config/client";
 import { useAllModels } from "../utils/hooks";
-import { Button, message, Popover, Select, Skeleton, Space } from 'antd';
-import { RightOutlined, CheckCircleOutlined } from '@ant-design/icons';
+import { Button, Collapse, Drawer, message, Popover, Select, Skeleton, Space } from 'antd';
+import {
+  FileOutlined,
+  FilePdfOutlined,
+  FileTextOutlined,
+  FileWordOutlined
+} from '@ant-design/icons';
+import { RightOutlined, CheckCircleOutlined, CaretRightOutlined, StarTwoTone } from '@ant-design/icons';
 import api from "@/app/api/api";
 
 const Markdown = dynamic(async () => (await import("./markdown")).Markdown, {
@@ -1625,6 +1631,119 @@ function _Chat() {
     }
   }, [couldStop])
 
+  interface FileIconProps {
+    fileName: string;
+  }
+
+  const FileIcon: React.FC<FileIconProps> = (props: FileIconProps) => {
+    const style = {
+      fontSize: '30px',
+      color: '#3875f6',
+    }
+
+    let icon = <FileOutlined style={style} />
+    if (props.fileName) {
+      const suffix = props.fileName.split('.').pop() || '';
+      switch (suffix) {
+        case 'pdf':
+          icon = <FilePdfOutlined style={style} />
+          break;
+        case 'txt':
+          icon = <FileTextOutlined style={style} />
+          break;
+        case 'doc':
+        case 'docx':
+          icon = <FileWordOutlined style={style} />
+          break;
+        default:
+          break;
+      }
+    }
+    return icon;
+  }
+
+  const [drawerOpen, setDrawerOpen] = useState(false);
+  const [drawerData, setDrawerData] = useState({
+    knowledge_id: '',
+    doc_name: '',
+    chunk_info: {
+      doc_id: '',
+      chunk_list: [],
+    }
+  });
+
+  const SliceDrawer: React.FC = () => {
+    const [pageLoading, setPageLoading] = useState(false);
+    const [list, setList] = useState([]);
+
+    const init = async () => {
+      setPageLoading(true);
+      try {
+        const res: any = await api.post('/deepseek/api/slicePage', {
+          knowledge_id: drawerData.knowledge_id,
+          chunk_info: drawerData.chunk_info,
+          pageNum: 1,
+          pageSize: 9999,
+        });
+        console.log(res.rows, 'res.rows');
+
+        setList(res.rows);
+      } catch (error) {
+        console.error(error);
+      } finally {
+        setPageLoading(false);
+      }
+    }
+
+    useEffect(() => {
+      init()
+    }, [])
+
+    return (
+      <Drawer
+        title={drawerData.doc_name}
+        loading={pageLoading}
+        open={drawerOpen}
+        onClose={() => {
+          setDrawerOpen(false);
+        }}
+      >
+        {list.map((item: any, index) => {
+          const score = parseFloat(item.rerankScore);
+          const formattedScore = isNaN(score) ? '0.00' : score.toFixed(2);
+          return <div
+            style={{
+              padding: 10,
+              background: '#fafafa',
+              borderRadius: 4,
+              marginBottom: 10
+            }}
+            key={item.sliceId}
+          >
+            <div
+              style={{
+                display: 'flex',
+                justifyContent: 'space-between',
+                alignItems: 'center',
+              }}
+            >
+              <div style={{ margin: '5px 0' }}>
+                片段{index + 1}
+              </div>
+              <div>
+                <StarTwoTone style={{ marginRight: 10 }} />
+                rerank得分{formattedScore}
+              </div>
+            </div>
+            <div>
+              {item.sliceText}
+            </div>
+          </div>
+        })}
+      </Drawer>
+    )
+  }
+
   return (
     <div className={styles.chat} key={session.id}>
       {
@@ -1757,7 +1876,6 @@ function _Chat() {
           messages.length > 1 ?
             <>
               {messages.map((message, i) => {
-                console.log(message.sliceInfo, 'sliceInfo');
                 const isUser = message.role === "user";
                 const isContext = i < context.length;
                 const showActions =
@@ -1868,8 +1986,64 @@ function _Chat() {
                         }
                         {
                           message.sliceInfo &&
-                          <div>
-                            {/* 渲染切片 */}
+                          <div style={{ marginTop: 10 }}>
+                            <Collapse
+                              bordered={false}
+                              expandIcon={({ isActive }) => <CaretRightOutlined rotate={isActive ? 90 : 0} />}
+                              items={[
+                                {
+                                  key: '1',
+                                  label: `查询到“${message.sliceInfo.doc.length}条”相关切片`,
+                                  children: <div>
+                                    {message.sliceInfo.doc.map((item, index) => {
+                                      return <div
+                                        style={{
+                                          padding: 10,
+                                          background: '#FFFFFF',
+                                          borderRadius: 4,
+                                          display: 'flex',
+                                          justifyContent: 'space-between',
+                                          alignItems: 'center',
+                                          marginTop: index ? 10 : 0,
+                                          cursor: 'pointer',
+                                        }}
+                                        key={item.doc_id}
+                                        onClick={() => {
+                                          setDrawerData({
+                                            knowledge_id: message.sliceInfo!.knowledge_id,
+                                            doc_name: item.doc_name,
+                                            chunk_info: {
+                                              doc_id: item.doc_id,
+                                              chunk_list: item.chunk_info_list,
+                                            }
+                                          });
+                                          setDrawerOpen(true);
+                                        }}
+                                      >
+                                        <div style={{ display: 'flex', alignItems: 'center' }}>
+                                          <FileIcon fileName={item.doc_name} />
+                                          <div style={{ marginLeft: 10 }}>
+                                            {item.doc_name}
+                                          </div>
+                                        </div>
+                                        <div style={{
+                                          padding: 10,
+                                          background: '#FAFAFA',
+                                          borderRadius: 4,
+                                          marginLeft: 20,
+                                        }}>
+                                          {item.chunk_nums}
+                                        </div>
+                                      </div>
+                                    })}
+                                  </div>,
+                                }
+                              ]}
+                            />
+                            {
+                              drawerOpen &&
+                              <SliceDrawer />
+                            }
                           </div>
                         }
                         <div className={styles["chat-message-item"]}>

+ 1 - 7
app/components/sidebar.tsx

@@ -425,13 +425,6 @@ export const SideBar = (props: { className?: string }) => {
                 url = `/bigmodel/api/dialog/detail/${key}`;
               }
               const res = await api.get(url);
-
-              // const document = {
-              //   id: "6e90c1c5-20ed-11f0-bcfc-22114d043191",
-              //   name: "ISHIGURO WEB EDI.pdf",
-              //   url: "http://xia0miduo.gicp.net:9000/papbtest///chatFiles/6e90c1c5-20ed-11f0-bcfc-22114d043191_ISHIGURO WEB EDI.pdf"
-              // }
-
               const list = res.data.map(((item: any) => {
                 return {
                   id: item.did,
@@ -439,6 +432,7 @@ export const SideBar = (props: { className?: string }) => {
                   date: item.create_time,
                   content: item.content,
                   document: item.document ? item.document : undefined,
+                  sliceInfo: item.sliceInfo ? item.sliceInfo : undefined,
                 }
               }))
               const session = {