Compare commits
	
		
			8 Commits
		
	
	
		
			90228512f7
			...
			c5fa739a95
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | c5fa739a95 | ||
|  | 70d1f40333 | ||
|  | 2866bcc7af | ||
|  | 2a57034c9d | ||
|  | 79a03ab6fc | ||
|  | 50f9e4354f | ||
|  | 8f27ca2e4e | ||
|  | ce333714b7 | 
| @ -1,30 +1,30 @@ | |||||||
| { | { | ||||||
|   "newChat": "New Chat", |     "newChat": "New Chat", | ||||||
|   "selectAPrompt": "Select a Prompt", |     "selectAPrompt": "Select a Prompt", | ||||||
|   "githubRepository": "GitHub Repository", |     "githubRepository": "GitHub Repository", | ||||||
|   "settings": "Settings", |     "settings": "Settings", | ||||||
|   "metering": "Metering", |     "metering": "Metering", | ||||||
|   "sidebarTitle": "Chat History", |     "sidebarTitle": "Chat History", | ||||||
|   "error": "Error", |     "error": "Error", | ||||||
|   "somethingWentWrong": "Something went wrong", |     "somethingWentWrong": "Something went wrong", | ||||||
|   "validationSelectModel": "Please select a model to continue", |     "validationSelectModel": "Please select a model to continue", | ||||||
|   "deleteHistoryConfirmation": "Are you sure you want to delete this history?", |     "deleteHistoryConfirmation": "Are you sure you want to delete this history?", | ||||||
|   "editHistoryTitle": "Enter a new title", |     "editHistoryTitle": "Enter a new title", | ||||||
|   "temporaryChat": "Temporary Chat", |     "temporaryChat": "Temporary Chat", | ||||||
|   "more": { |     "more": { | ||||||
|     "copy": { |         "copy": { | ||||||
|       "group": "Copy", |             "group": "Copy", | ||||||
|       "asText": "Copy as Text", |             "asText": "Copy as Text", | ||||||
|       "asMarkdown": "Copy as Markdown", |             "asMarkdown": "Copy as Markdown", | ||||||
|       "success": "Copied to clipboard!" |             "success": "Copied to clipboard!" | ||||||
|     }, |         }, | ||||||
|     "download": { |         "download": { | ||||||
|       "group": "Download", |             "group": "Download", | ||||||
|       "text": "Text File (.txt)", |             "text": "Text File (.txt)", | ||||||
|       "markdown": "Markdown (.md)", |             "markdown": "Markdown (.md)", | ||||||
|       "json": "JSON File (.json)", |             "json": "JSON File (.json)", | ||||||
|       "image": "Image (.png)" |             "image": "Image (.png)" | ||||||
|     }, |         }, | ||||||
|     "share": "Share" |         "share": "Share" | ||||||
|   } |     } | ||||||
| } | } | ||||||
| @ -1,29 +1,29 @@ | |||||||
| { | { | ||||||
|   "newChat": "新聊天", |     "newChat": "新聊天", | ||||||
|   "selectAPrompt": "选择一个提示词", |     "selectAPrompt": "选择一个提示词", | ||||||
|   "githubRepository": "GitHub 仓库", |     "githubRepository": "GitHub 仓库", | ||||||
|   "settings": "设置", |     "settings": "设置", | ||||||
|   "metering": "计量", |     "metering": "计量", | ||||||
|   "sidebarTitle": "聊天历史", |     "sidebarTitle": "聊天历史", | ||||||
|   "error": "错误", |     "error": "错误", | ||||||
|   "somethingWentWrong": "出现了错误", |     "somethingWentWrong": "出现了错误", | ||||||
|   "validationSelectModel": "请选择一个模型以继续", |     "validationSelectModel": "请选择一个模型以继续", | ||||||
|   "deleteHistoryConfirmation": "你确定要删除这个历史记录吗?", |     "deleteHistoryConfirmation": "你确定要删除这个历史记录吗?", | ||||||
|   "editHistoryTitle": "输入一个新的标题", |     "editHistoryTitle": "输入一个新的标题", | ||||||
|   "temporaryChat": "临时聊天", |     "temporaryChat": "临时聊天", | ||||||
|   "more": { |     "more": { | ||||||
|     "copy": { |         "copy": { | ||||||
|       "group": "复制", |             "group": "复制", | ||||||
|       "asText": "复制为文本", |             "asText": "复制为文本", | ||||||
|       "asMarkdown": "复制为 Markdown", |             "asMarkdown": "复制为 Markdown", | ||||||
|       "success": "已复制到剪贴板!" |             "success": "已复制到剪贴板!" | ||||||
|     }, |         }, | ||||||
|     "download": { |         "download": { | ||||||
|       "group": "下载", |             "group": "下载", | ||||||
|       "text": "文本文件 (.txt)", |             "text": "文本文件 (.txt)", | ||||||
|       "markdown": "Markdown 文件 (.md)", |             "markdown": "Markdown 文件 (.md)", | ||||||
|       "json": "JSON 文件 (.json)" |             "json": "JSON 文件 (.json)" | ||||||
|     }, |         }, | ||||||
|     "share": "分享" |         "share": "分享" | ||||||
|   } |     } | ||||||
| } | } | ||||||
| @ -9,7 +9,12 @@ import { | |||||||
|   Pen, |   Pen, | ||||||
|   PlayIcon, |   PlayIcon, | ||||||
|   RotateCcw, |   RotateCcw, | ||||||
|   Square |   Square, | ||||||
|  |   Star, | ||||||
|  |   ThumbsUp, | ||||||
|  |   ThumbsDown, | ||||||
|  |   MessageSquareShare, | ||||||
|  |   ArrowUpSquare | ||||||
| } from "lucide-react" | } from "lucide-react" | ||||||
| import { EditMessageForm } from "./EditMessageForm" | import { EditMessageForm } from "./EditMessageForm" | ||||||
| import { useTranslation } from "react-i18next" | import { useTranslation } from "react-i18next" | ||||||
| @ -316,6 +321,51 @@ export const PlaygroundMessage = (props: Props) => { | |||||||
|                   </button> |                   </button> | ||||||
|                 </Tooltip> |                 </Tooltip> | ||||||
|               )} |               )} | ||||||
|  |               { ( | ||||||
|  |                 <Tooltip title="收藏"> | ||||||
|  |                   <button | ||||||
|  |                     aria-label="收藏" | ||||||
|  |                     className="flex items-center justify-center w-6 h-6 rounded-full bg-gray-100 dark:bg-gray-800 hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500"> | ||||||
|  |                     <Star className="w-3 h-3 text-gray-400 group-hover:text-gray-500" /> | ||||||
|  |                   </button> | ||||||
|  |                 </Tooltip> | ||||||
|  |               )} | ||||||
|  |               { ( | ||||||
|  |                 <Tooltip title="发布语用"> | ||||||
|  |                   <button | ||||||
|  |                     aria-label="发布语用" | ||||||
|  |                     className="flex items-center justify-center w-6 h-6 rounded-full bg-gray-100 dark:bg-gray-800 hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500"> | ||||||
|  |                     <ArrowUpSquare className="w-3 h-3 text-gray-400 group-hover:text-gray-500" /> | ||||||
|  |                   </button> | ||||||
|  |                 </Tooltip> | ||||||
|  |               )} | ||||||
|  |               { ( | ||||||
|  |                 <Tooltip title="发布对话"> | ||||||
|  |                   <button | ||||||
|  |                     aria-label="发布对话" | ||||||
|  |                     className="flex items-center justify-center w-6 h-6 rounded-full bg-gray-100 dark:bg-gray-800 hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500"> | ||||||
|  |                     <MessageSquareShare className="w-3 h-3 text-gray-400 group-hover:text-gray-500" /> | ||||||
|  |                   </button> | ||||||
|  |                 </Tooltip> | ||||||
|  |               )} | ||||||
|  |               { ( | ||||||
|  |                 <Tooltip title="点赞"> | ||||||
|  |                   <button | ||||||
|  |                     aria-label="点赞" | ||||||
|  |                     className="flex items-center justify-center w-6 h-6 rounded-full bg-gray-100 dark:bg-gray-800 hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500"> | ||||||
|  |                     <ThumbsUp className="w-3 h-3 text-gray-400 group-hover:text-gray-500" /> | ||||||
|  |                   </button> | ||||||
|  |                 </Tooltip> | ||||||
|  |               )} | ||||||
|  |               { ( | ||||||
|  |                 <Tooltip title="点踩"> | ||||||
|  |                   <button | ||||||
|  |                     aria-label="点踩" | ||||||
|  |                     className="flex items-center justify-center w-6 h-6 rounded-full bg-gray-100 dark:bg-gray-800 hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500"> | ||||||
|  |                     <ThumbsDown className="w-3 h-3 text-gray-400 group-hover:text-gray-500" /> | ||||||
|  |                   </button> | ||||||
|  |                 </Tooltip> | ||||||
|  |               )} | ||||||
|             </div> |             </div> | ||||||
|           ) : ( |           ) : ( | ||||||
|             // add invisible div to prevent layout shift
 |             // add invisible div to prevent layout shift
 | ||||||
|  | |||||||
| @ -5,7 +5,7 @@ import { | |||||||
|   ChevronRight, |   ChevronRight, | ||||||
|   CogIcon, |   CogIcon, | ||||||
|   ComputerIcon, |   ComputerIcon, | ||||||
|   Slice, |   GaugeCircle, | ||||||
|   GithubIcon, |   GithubIcon, | ||||||
|   PanelLeftIcon, |   PanelLeftIcon, | ||||||
|   ZapIcon |   ZapIcon | ||||||
| @ -245,7 +245,7 @@ export const Header: React.FC<Props> = ({ | |||||||
|               <NavLink |               <NavLink | ||||||
|                 to="/metering" |                 to="/metering" | ||||||
|                 className="!text-gray-500 dark:text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 transition-colors"> |                 className="!text-gray-500 dark:text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 transition-colors"> | ||||||
|                 <Slice className="w-6 h-6" /> |                 <GaugeCircle className="w-6 h-6" /> | ||||||
|               </NavLink> |               </NavLink> | ||||||
|             </Tooltip> |             </Tooltip> | ||||||
|           </div> |           </div> | ||||||
|  | |||||||
| @ -1,15 +1,15 @@ | |||||||
| import React, { useMemo } from "react" | import React, { useMemo } from "react" | ||||||
| import { ChatMessage, useStoreMessageOption } from "@/store/option" | import { MeteringEntry, useStoreMessageOption } from "@/store/option" | ||||||
| import { Card, List, Table, Tag, Space, TableProps, Tooltip } from "antd" | import { Card, List, Table, Tag, Space, TableProps, Tooltip } from "antd" | ||||||
| import { NavLink } from "react-router-dom" | import { NavLink } from "react-router-dom" | ||||||
| import { formatDate } from "@/utils/date" | import { formatDate } from "@/utils/date" | ||||||
| 
 | 
 | ||||||
| const columns: TableProps<ChatMessage>["columns"] = [ | const columns: TableProps<MeteringEntry>["columns"] = [ | ||||||
|   { |   { | ||||||
|     title: "id", |     title: '序号', | ||||||
|     dataIndex: "id", |     key: 'index', | ||||||
|     key: "id", |     width: 100, | ||||||
|     width: "13%" |     render: (_text, _record, index) => index + 1, // 索引从0开始,+1后从1显示
 | ||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|     title: "问题", |     title: "问题", | ||||||
| @ -32,8 +32,8 @@ const columns: TableProps<ChatMessage>["columns"] = [ | |||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|     title: "思维链", |     title: "思维链", | ||||||
|     key: "thinkingChain", |     key: "cot", | ||||||
|     dataIndex: "thinkingChain", |     dataIndex: "cot", | ||||||
|     ellipsis: { |     ellipsis: { | ||||||
|       showTitle: false |       showTitle: false | ||||||
|     }, |     }, | ||||||
| @ -66,8 +66,8 @@ const columns: TableProps<ChatMessage>["columns"] = [ | |||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|     title: "数联网token", |     title: "数联网token", | ||||||
|     dataIndex: "iodDataTokenCount", |     dataIndex: "iodTokenCount", | ||||||
|     key: "iodDataTokenCount" |     key: "iodTokenCount" | ||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|     title: "大模型token", |     title: "大模型token", | ||||||
| @ -84,7 +84,7 @@ const columns: TableProps<ChatMessage>["columns"] = [ | |||||||
|     dataIndex: "date", |     dataIndex: "date", | ||||||
|     key: "date", |     key: "date", | ||||||
|     render: (date) => { |     render: (date) => { | ||||||
|       return <div>{formatDate(date)}</div> |       return <div>{formatDate(date ?? new Date())}</div> | ||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
| @ -108,17 +108,17 @@ const columns: TableProps<ChatMessage>["columns"] = [ | |||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
| export const MeteringDetail = () => { | export const MeteringDetail = () => { | ||||||
|   const { chatMessages } = useStoreMessageOption() |   const { meteringEntries } = useStoreMessageOption() | ||||||
| 
 | 
 | ||||||
|   const data = useMemo( |   const data = useMemo( | ||||||
|     () => [ |     () => [ | ||||||
|       { |       { | ||||||
|         key: "对话数量", |         key: "对话数量", | ||||||
|         value: chatMessages.length |         value: meteringEntries.length | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         key: "数联网输入token数", |         key: "数联网输入token数", | ||||||
|         value: chatMessages.reduce((acc, cur) => { |         value: meteringEntries.reduce((acc, cur) => { | ||||||
|           for (const item of cur.iodKeywords) { |           for (const item of cur.iodKeywords) { | ||||||
|             acc += item.length |             acc += item.length | ||||||
|           } |           } | ||||||
| @ -127,24 +127,24 @@ export const MeteringDetail = () => { | |||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         key: "数联网输出token数", |         key: "数联网输出token数", | ||||||
|         value: chatMessages.reduce((acc, cur) => acc + cur.iodDataTokenCount, 0) |         value: meteringEntries.reduce((acc, cur) => acc + cur.iodTokenCount, 0) | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         key: "大模型输入token数", |         key: "大模型输入token数", | ||||||
|         value: chatMessages.reduce( |         value: meteringEntries.reduce( | ||||||
|           (acc, cur) => acc + cur.modelInputTokenCount, |           (acc, cur) => acc + cur.modelInputTokenCount, | ||||||
|           0 |           0 | ||||||
|         ) |         ) | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         key: "大模型输出token数", |         key: "大模型输出token数", | ||||||
|         value: chatMessages.reduce( |         value: meteringEntries.reduce( | ||||||
|           (acc, cur) => acc + cur.modelOutputTokenCount, |           (acc, cur) => acc + cur.modelOutputTokenCount, | ||||||
|           0 |           0 | ||||||
|         ) |         ) | ||||||
|       } |       } | ||||||
|     ], |     ], | ||||||
|     [chatMessages] |     [meteringEntries] | ||||||
|   ) |   ) | ||||||
|   return ( |   return ( | ||||||
|     <div className="p-4  pt-[4rem]"> |     <div className="p-4  pt-[4rem]"> | ||||||
| @ -159,7 +159,7 @@ export const MeteringDetail = () => { | |||||||
|         )} |         )} | ||||||
|       /> |       /> | ||||||
| 
 | 
 | ||||||
|       <Table<ChatMessage> columns={columns} dataSource={chatMessages} /> |       <Table<MeteringEntry> columns={columns} dataSource={meteringEntries} /> | ||||||
|     </div> |     </div> | ||||||
|   ) |   ) | ||||||
| } | } | ||||||
|  | |||||||
| @ -61,11 +61,11 @@ const columns: TableProps<DataType>["columns"] = [ | |||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
| export const ListDetail = () => { | export const ListDetail = () => { | ||||||
|   const { chatMessages } = useStoreMessageOption() |   const { meteringEntries } = useStoreMessageOption() | ||||||
|   const { id } = useParams() |   const { id } = useParams() | ||||||
|   const record = useMemo( |   const record = useMemo( | ||||||
|     () => chatMessages.find((item) => item.id === id), |     () => meteringEntries.find((item) => item.id === id), | ||||||
|     [chatMessages] |     [meteringEntries] | ||||||
|   ) |   ) | ||||||
| 
 | 
 | ||||||
|   const modelData = useMemo( |   const modelData = useMemo( | ||||||
| @ -8,7 +8,7 @@ import { | |||||||
|   promptForRag, |   promptForRag, | ||||||
|   systemPromptForNonRagOption |   systemPromptForNonRagOption | ||||||
| } from "~/services/ollama" | } from "~/services/ollama" | ||||||
| import { type ChatHistory, ChatMessage, type Message } from "~/store/option" | import type { ChatHistory, Message, MeteringEntry } from "~/store/option" | ||||||
| import { SystemMessage } from "@langchain/core/messages" | import { SystemMessage } from "@langchain/core/messages" | ||||||
| import { useStoreMessageOption } from "~/store/option" | import { useStoreMessageOption } from "~/store/option" | ||||||
| import { | import { | ||||||
| @ -55,8 +55,8 @@ export const useMessageOption = () => { | |||||||
|   const { |   const { | ||||||
|     history, |     history, | ||||||
|     setHistory, |     setHistory, | ||||||
|     chatMessages, |     meteringEntries, | ||||||
|     setChatMessages, |     setMeteringEntries, | ||||||
|     setStreaming, |     setStreaming, | ||||||
|     streaming, |     streaming, | ||||||
|     setIsFirstMessage, |     setIsFirstMessage, | ||||||
| @ -114,23 +114,24 @@ export const useMessageOption = () => { | |||||||
|       setWebSearch(true) |       setWebSearch(true) | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   // 从最后的结果中解析出 思维链 和 结果
 | 
 | ||||||
|  |   // 从最后的结果中解析出 思维链 (Chain-of-Thought) 和 结果
 | ||||||
|   const responseResolver = (msg: string) => { |   const responseResolver = (msg: string) => { | ||||||
|     const thinkStart = msg.indexOf("<think>") |     const cotStart = msg.indexOf("<think>") | ||||||
|     const thinkEnd = msg.indexOf("</think>") |     const cotEnd = msg.indexOf("</think>") | ||||||
|     let think = "" |     let cot = "" | ||||||
|     let content = "" |     let content = "" | ||||||
|     if (thinkStart > -1 && thinkEnd > -1) { |     if (cotStart > -1 && cotEnd > -1) { | ||||||
|       think = msg.substring(thinkStart + 7, thinkEnd) |       cot = msg.substring(cotStart + 7, cotEnd) | ||||||
|       content = msg.substring(thinkEnd + 8) |       content = msg.substring(cotEnd + 8) | ||||||
|     } else { |     } else { | ||||||
|       content = msg |       content = msg | ||||||
|     } |     } | ||||||
|     // 去掉换行符
 |     // 去掉换行符
 | ||||||
|     think = think.replace(/\n/g, "") |     cot = cot.replace(/\n/g, "") | ||||||
|     content = content.replace(/\n/g, "") |     content = content.replace(/\n/g, "") | ||||||
|     return { |     return { | ||||||
|       think, |       cot: cot, | ||||||
|       content |       content | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| @ -190,10 +191,11 @@ export const useMessageOption = () => { | |||||||
|     }) |     }) | ||||||
|     let newMessage: Message[] = [] |     let newMessage: Message[] = [] | ||||||
|     let generateMessageId = generateID() |     let generateMessageId = generateID() | ||||||
|     const chatMessage: ChatMessage = { |     const meter: MeteringEntry = { | ||||||
|       id: generateMessageId, |       id: generateMessageId, | ||||||
|       queryContent: message |       queryContent: message, | ||||||
|     } as ChatMessage |       date: new Date() | ||||||
|  |     } as MeteringEntry | ||||||
| 
 | 
 | ||||||
|     if (!isRegenerate) { |     if (!isRegenerate) { | ||||||
|       newMessage = [ |       newMessage = [ | ||||||
| @ -316,14 +318,14 @@ export const useMessageOption = () => { | |||||||
|           .map((k) => k.trim()) |           .map((k) => k.trim()) | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       const { prompt, webSources, iodSources, iodData, iodDataTokenCount } = |       const { prompt, webSources, iodSources, iodSearchResults: iodData, iodTokenCount } = | ||||||
|         await getSystemPromptForWeb(query, keywords, webSearch, iodSearch) |         await getSystemPromptForWeb(query, keywords, webSearch, iodSearch) | ||||||
|       console.log("prompt:\n" + prompt) |       console.log("prompt:\n" + prompt) | ||||||
|       setIsSearchingInternet(false) |       setIsSearchingInternet(false) | ||||||
|       chatMessage.prompt = prompt |       meter.prompt = prompt | ||||||
|       chatMessage.iodKeywords = keywords |       meter.iodKeywords = keywords | ||||||
|       chatMessage.iodData = iodData |       meter.iodData = iodData | ||||||
|       chatMessage.iodDataTokenCount = iodDataTokenCount |       meter.iodTokenCount = iodTokenCount | ||||||
| 
 | 
 | ||||||
|       //  message = message.trim().replaceAll("\n", " ")
 |       //  message = message.trim().replaceAll("\n", " ")
 | ||||||
| 
 | 
 | ||||||
| @ -384,6 +386,7 @@ export const useMessageOption = () => { | |||||||
|         } |         } | ||||||
|       ) |       ) | ||||||
|       let count = 0 |       let count = 0 | ||||||
|  |       const chatStartTime = new Date() | ||||||
|       let reasoningStartTime: Date | undefined = undefined |       let reasoningStartTime: Date | undefined = undefined | ||||||
|       let reasoningEndTime: Date | undefined = undefined |       let reasoningEndTime: Date | undefined = undefined | ||||||
|       let apiReasoning = false |       let apiReasoning = false | ||||||
| @ -484,17 +487,22 @@ export const useMessageOption = () => { | |||||||
|       setIsProcessing(false) |       setIsProcessing(false) | ||||||
|       setStreaming(false) |       setStreaming(false) | ||||||
| 
 | 
 | ||||||
|       chatMessage.modelInputTokenCount = generationInfo?.prompt_eval_count ?? 0 |       // Save metering entry
 | ||||||
|       chatMessage.modelOutputTokenCount = generationInfo?.eval_count ?? 0 |       const { cot, content } = responseResolver(fullText) | ||||||
|       chatMessage.model = generationInfo?.model ?? "" |       setMeteringEntries([ { | ||||||
|       chatMessage.relatedDataCount = iodData?.length ?? 0 |         ...meter, | ||||||
|       chatMessage.timeTaken = timetaken |         modelInputTokenCount: prompt.length, | ||||||
|       chatMessage.date = reasoningStartTime |         modelOutputTokenCount: fullText.length, | ||||||
|       const { think, content } = responseResolver(fullText) |         model: ollama.modelName, | ||||||
|       chatMessage.thinkingChain = think |         relatedDataCount: iodData?.length ?? 0, | ||||||
|       chatMessage.responseContent = content |         timeTaken: new Date().getTime() - meter.date.getTime(), | ||||||
|       chatMessage.modelResponseContent = fullText |         date: chatStartTime, | ||||||
|       setChatMessages([...chatMessages, chatMessage]) |         cot, | ||||||
|  |         responseContent: content, | ||||||
|  |         modelResponseContent: fullText, | ||||||
|  |       }, | ||||||
|  |         ...meteringEntries, | ||||||
|  |       ]) | ||||||
|     } catch (e) { |     } catch (e) { | ||||||
|       const errorSave = await saveMessageOnError({ |       const errorSave = await saveMessageOnError({ | ||||||
|         e, |         e, | ||||||
|  | |||||||
| @ -72,7 +72,7 @@ export const pageAssistModel = async ({ | |||||||
|         configuration: { |         configuration: { | ||||||
|           apiKey: providerInfo.apiKey || "temp", |           apiKey: providerInfo.apiKey || "temp", | ||||||
|           baseURL: providerInfo.baseUrl || "" |           baseURL: providerInfo.baseUrl || "" | ||||||
|         } |         }, | ||||||
|       }) as any |       }) as any | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -85,7 +85,7 @@ export const pageAssistModel = async ({ | |||||||
|       configuration: { |       configuration: { | ||||||
|         apiKey: providerInfo.apiKey || "temp", |         apiKey: providerInfo.apiKey || "temp", | ||||||
|         baseURL: providerInfo.baseUrl || "" |         baseURL: providerInfo.baseUrl || "" | ||||||
|       } |       }, | ||||||
|     }) as any |     }) as any | ||||||
|   } |   } | ||||||
|   return new ChatOllama({ |   return new ChatOllama({ | ||||||
|  | |||||||
| @ -30,49 +30,13 @@ export type ChatHistory = { | |||||||
|   messageType?: string |   messageType?: string | ||||||
| }[] | }[] | ||||||
| 
 | 
 | ||||||
| export type ChatMessage = { |  | ||||||
|   id: string |  | ||||||
|   // 问题
 |  | ||||||
|   queryContent: string |  | ||||||
|   // 提示词全文
 |  | ||||||
|   prompt: string |  | ||||||
|   // 思维链(只有深度思考时有)
 |  | ||||||
|   thinkingChain?: string |  | ||||||
|   // 回答
 |  | ||||||
|   responseContent: string |  | ||||||
|   // 关联数据个数
 |  | ||||||
|   relatedDataCount: number |  | ||||||
|   // 数联网输入token
 |  | ||||||
|   iodInputToken: string |  | ||||||
|   // 数联网输出token
 |  | ||||||
|   iodOutputToken: string |  | ||||||
|   // 大模型输入token数量
 |  | ||||||
|   modelInputTokenCount: number |  | ||||||
|   // 大模型输出token数量
 |  | ||||||
|   modelOutputTokenCount: number |  | ||||||
|   // 日期
 |  | ||||||
|   date: Date |  | ||||||
|   // 耗时
 |  | ||||||
|   timeTaken: number |  | ||||||
|   // 大模型回答的全部内容
 |  | ||||||
|   modelResponseContent: string |  | ||||||
|   // iod的全部内容的token数量
 |  | ||||||
|   iodDataTokenCount: number |  | ||||||
|   // iod返回的数据
 |  | ||||||
|   iodData: any[] |  | ||||||
|   // iod keywords
 |  | ||||||
|   iodKeywords: string[] |  | ||||||
|   // 模型
 |  | ||||||
|   model: string |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| type State = { | type State = { | ||||||
|   messages: Message[] |   messages: Message[] | ||||||
|   setMessages: (messages: Message[]) => void |   setMessages: (messages: Message[]) => void | ||||||
|   history: ChatHistory |   history: ChatHistory | ||||||
|   setHistory: (history: ChatHistory) => void |   setHistory: (history: ChatHistory) => void | ||||||
|   chatMessages: ChatMessage[] |   meteringEntries: MeteringEntry[] | ||||||
|   setChatMessages: (chatMessages: ChatMessage[]) => void |   setMeteringEntries: (meteringEntries: MeteringEntry[]) => void | ||||||
|   streaming: boolean |   streaming: boolean | ||||||
|   setStreaming: (streaming: boolean) => void |   setStreaming: (streaming: boolean) => void | ||||||
|   isFirstMessage: boolean |   isFirstMessage: boolean | ||||||
| @ -115,13 +79,49 @@ type State = { | |||||||
|   setUseOCR: (useOCR: boolean) => void |   setUseOCR: (useOCR: boolean) => void | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | export type MeteringEntry = { | ||||||
|  |   id: string | ||||||
|  |   // 问题
 | ||||||
|  |   queryContent: string | ||||||
|  |   // 提示词全文
 | ||||||
|  |   prompt: string | ||||||
|  |   // 思维链(只有深度思考时有)
 | ||||||
|  |   cot?: string | ||||||
|  |   // 回答
 | ||||||
|  |   responseContent: string | ||||||
|  |   // 关联数据个数
 | ||||||
|  |   relatedDataCount: number | ||||||
|  |   // 数联网输入token
 | ||||||
|  |   iodInputToken: string | ||||||
|  |   // 数联网输出token
 | ||||||
|  |   iodOutputToken: string | ||||||
|  |   // 大模型输入token数量
 | ||||||
|  |   modelInputTokenCount: number | ||||||
|  |   // 大模型输出token数量
 | ||||||
|  |   modelOutputTokenCount: number | ||||||
|  |   // 日期
 | ||||||
|  |   date: Date | ||||||
|  |   // 耗时
 | ||||||
|  |   timeTaken: number | ||||||
|  |   // 大模型回答的全部内容
 | ||||||
|  |   modelResponseContent: string | ||||||
|  |   // iod的全部内容的token数量
 | ||||||
|  |   iodTokenCount: number | ||||||
|  |   // iod返回的数据
 | ||||||
|  |   iodData: any[] | ||||||
|  |   // iod keywords
 | ||||||
|  |   iodKeywords: string[] | ||||||
|  |   // 模型
 | ||||||
|  |   model: string | ||||||
|  | } | ||||||
|  | 
 | ||||||
| export const useStoreMessageOption = create<State>((set) => ({ | export const useStoreMessageOption = create<State>((set) => ({ | ||||||
|   messages: [], |   messages: [], | ||||||
|   setMessages: (messages) => set({ messages }), |   setMessages: (messages) => set({ messages }), | ||||||
|   history: [], |   history: [], | ||||||
|   setHistory: (history) => set({ history }), |   setHistory: (history) => set({ history }), | ||||||
|   chatMessages: [], |   meteringEntries: [], | ||||||
|   setChatMessages: (chatMessages) => set({ chatMessages }), |   setMeteringEntries: (meteringEntries) => set({ meteringEntries }), | ||||||
|   streaming: false, |   streaming: false, | ||||||
|   setStreaming: (streaming) => set({ streaming }), |   setStreaming: (streaming) => set({ streaming }), | ||||||
|   isFirstMessage: true, |   isFirstMessage: true, | ||||||
|  | |||||||
							
								
								
									
										21
									
								
								src/web/1.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/web/1.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,21 @@ | |||||||
|  | { | ||||||
|  | 	"action": "executeContract", | ||||||
|  | 	"contractID": "BDBrowser", | ||||||
|  | 	"operation": "sendRequestDirectly", | ||||||
|  | 	"arg": { | ||||||
|  | 		"id": "670E241C9937B3537047C87053E3AA36", | ||||||
|  | 		"doipUrl": "tcp://reg01.public.internetofdata.cn:21037", | ||||||
|  | 		"op": "Search", | ||||||
|  | 		"attributes": { | ||||||
|  | 			"offset": 2100, | ||||||
|  | 			"count": 5, | ||||||
|  | 			"bodyBase64Encoded": false, | ||||||
|  | 			"searchMode": [ | ||||||
|  | 				{ "key": "data_type", "type": "MUST", "value": "paper" }, | ||||||
|  | 				{ "key": "title", "type": "MUST", "value": "Number_1" }, | ||||||
|  | 				{ "key": "description", "type": "MUST", "value": "Number_1" } | ||||||
|  | 			] | ||||||
|  | 		}, | ||||||
|  | 		"body": "" | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										33
									
								
								src/web/2.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/web/2.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,33 @@ | |||||||
|  | const ollama = await pageAssistModel({ | ||||||
|  |   model: selectedModel!, | ||||||
|  |   baseUrl: cleanUrl(url), | ||||||
|  |   keepAlive: | ||||||
|  |     currentChatModelSettings?.keepAlive ?? userDefaultModelSettings?.keepAlive, | ||||||
|  |   temperature: | ||||||
|  |     currentChatModelSettings?.temperature ?? | ||||||
|  |     userDefaultModelSettings?.temperature, | ||||||
|  |   topK: currentChatModelSettings?.topK ?? userDefaultModelSettings?.topK, | ||||||
|  |   topP: currentChatModelSettings?.topP ?? userDefaultModelSettings?.topP, | ||||||
|  |   numCtx: currentChatModelSettings?.numCtx ?? userDefaultModelSettings?.numCtx, | ||||||
|  |   seed: currentChatModelSettings?.seed, | ||||||
|  |   numGpu: currentChatModelSettings?.numGpu ?? userDefaultModelSettings?.numGpu, | ||||||
|  |   numPredict: | ||||||
|  |     currentChatModelSettings?.numPredict ?? | ||||||
|  |     userDefaultModelSettings?.numPredict, | ||||||
|  |   useMMap: | ||||||
|  |     currentChatModelSettings?.useMMap ?? userDefaultModelSettings?.useMMap, | ||||||
|  |   minP: currentChatModelSettings?.minP ?? userDefaultModelSettings?.minP, | ||||||
|  |   repeatLastN: | ||||||
|  |     currentChatModelSettings?.repeatLastN ?? | ||||||
|  |     userDefaultModelSettings?.repeatLastN, | ||||||
|  |   repeatPenalty: | ||||||
|  |     currentChatModelSettings?.repeatPenalty ?? | ||||||
|  |     userDefaultModelSettings?.repeatPenalty, | ||||||
|  |   tfsZ: currentChatModelSettings?.tfsZ ?? userDefaultModelSettings?.tfsZ, | ||||||
|  |   numKeep: | ||||||
|  |     currentChatModelSettings?.numKeep ?? userDefaultModelSettings?.numKeep, | ||||||
|  |   numThread: | ||||||
|  |     currentChatModelSettings?.numThread ?? userDefaultModelSettings?.numThread, | ||||||
|  |   useMlock: | ||||||
|  |     currentChatModelSettings?.useMlock ?? userDefaultModelSettings?.useMlock | ||||||
|  | }) | ||||||
| @ -101,8 +101,8 @@ export const getSystemPromptForWeb = async ( | |||||||
|           name: res.name, |           name: res.name, | ||||||
|           url: res.url, |           url: res.url, | ||||||
|           data_space: res.data_space, |           data_space: res.data_space, | ||||||
|  |           content: res.content || res.description, | ||||||
|           tokenCount: (res.content || res.description)?.length ?? 0, |           tokenCount: (res.content || res.description)?.length ?? 0, | ||||||
|           content: res.content || res.description |  | ||||||
|         })) |         })) | ||||||
| 
 | 
 | ||||||
|     const iod_search_results = _iodSearchResults |     const iod_search_results = _iodSearchResults | ||||||
| @ -140,15 +140,17 @@ export const getSystemPromptForWeb = async ( | |||||||
|         } |         } | ||||||
|       }), |       }), | ||||||
|       iodSources: iodSearchResults, |       iodSources: iodSearchResults, | ||||||
|       iodData: _iodSearchResults, |       iodSearchResults: _iodSearchResults, | ||||||
|       iodDataTokenCount: _iodSearchResults.reduce((acc, cur) => (acc + cur.content.length), 0) |       iodTokenCount: _iodSearchResults.reduce((acc, cur) => (acc + cur.content.length), 0) | ||||||
|     } |     } | ||||||
|   } catch (e) { |   } catch (e) { | ||||||
|     console.error(e) |     console.error(e) | ||||||
|     return { |     return { | ||||||
|       prompt: "", |       prompt: "", | ||||||
|       webSources: [], |       webSources: [], | ||||||
|       iodSources: [] |       iodSources: [], | ||||||
|  |       iodSearchResults: [], | ||||||
|  |       iodTokenCount: 0, | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user