Compare commits
2 Commits
6bb9247c6c
...
6f386709e2
Author | SHA1 | Date | |
---|---|---|---|
|
6f386709e2 | ||
|
2b4885ae2d |
@ -11,8 +11,7 @@ const defaultData: IodRegistryEntry[] = [
|
|||||||
{
|
{
|
||||||
name: "固态电池固体电解质材料数据集",
|
name: "固态电池固体电解质材料数据集",
|
||||||
doId: "CSTR:16666.11.nbsdc.9bjqrscd",
|
doId: "CSTR:16666.11.nbsdc.9bjqrscd",
|
||||||
description:
|
description: "国家基础学科公共科学数据中心"
|
||||||
"国家基础学科公共科学数据中心"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "固体颗粒物与流体耦合",
|
name: "固体颗粒物与流体耦合",
|
||||||
@ -98,31 +97,22 @@ type Props = {
|
|||||||
className?: string
|
className?: string
|
||||||
}
|
}
|
||||||
export const PlaygroundData: React.FC<Props> = ({ className }) => {
|
export const PlaygroundData: React.FC<Props> = ({ className }) => {
|
||||||
const { messages, iodLoading, currentMessageId, iodSearch } =
|
const { iodLoading } = useMessageOption()
|
||||||
useMessageOption()
|
|
||||||
|
|
||||||
const { setShowPlayground, setDetailHeader, setDetailMain } =
|
const {
|
||||||
useIodPlaygroundContext()
|
setShowPlayground,
|
||||||
|
setDetailHeader,
|
||||||
|
setDetailMain,
|
||||||
|
currentIodMessage
|
||||||
|
} = useIodPlaygroundContext()
|
||||||
|
|
||||||
const data = useMemo<IodRegistryEntry[]>(() => {
|
const data = useMemo<IodRegistryEntry[]>(() => {
|
||||||
// 确保loading状态时数据大于3
|
return currentIodMessage ? currentIodMessage.data?.data ?? [] : defaultData
|
||||||
if (iodLoading) {
|
}, [currentIodMessage])
|
||||||
return defaultData
|
|
||||||
}
|
|
||||||
|
|
||||||
if (messages.length && iodSearch) {
|
|
||||||
const currentMessage = messages?.find(
|
|
||||||
(message) => message.id === currentMessageId
|
|
||||||
)
|
|
||||||
return currentMessage?.iodSources.data.data ?? []
|
|
||||||
}
|
|
||||||
|
|
||||||
return defaultData
|
|
||||||
}, [currentMessageId, messages, iodLoading, iodSearch])
|
|
||||||
|
|
||||||
const title = useMemo(() => {
|
const title = useMemo(() => {
|
||||||
return messages.length > 0 ? "推荐数据" : "热点数据"
|
return currentIodMessage ? "推荐数据" : "热点数据"
|
||||||
}, [messages])
|
}, [currentIodMessage])
|
||||||
|
|
||||||
const showMore = () => {
|
const showMore = () => {
|
||||||
setShowPlayground(false)
|
setShowPlayground(false)
|
||||||
@ -133,7 +123,7 @@ export const PlaygroundData: React.FC<Props> = ({ className }) => {
|
|||||||
onClick={() => setShowPlayground(false)}
|
onClick={() => setShowPlayground(false)}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
setDetailMain(<Main loading={iodLoading} data={data} truncate={false} />)
|
setDetailMain(<Main loading={iodLoading && Boolean(currentIodMessage)} data={data} truncate={false} />)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -142,7 +132,7 @@ export const PlaygroundData: React.FC<Props> = ({ className }) => {
|
|||||||
{/* 数据导航 */}
|
{/* 数据导航 */}
|
||||||
<Header title={title} onClick={showMore} />
|
<Header title={title} onClick={showMore} />
|
||||||
{/* 数据列表 */}
|
{/* 数据列表 */}
|
||||||
<Main loading={iodLoading} data={data.slice(0, 3)} />
|
<Main loading={iodLoading && Boolean(currentIodMessage)} data={data.slice(0, 3)} />
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
)
|
)
|
||||||
|
@ -10,6 +10,7 @@ import { DatasetIcon } from "@/components/Icons/Dataset.tsx"
|
|||||||
import { TechCompanyIcon } from "@/components/Icons/TechCompany.tsx"
|
import { TechCompanyIcon } from "@/components/Icons/TechCompany.tsx"
|
||||||
import { ResearchInstitutesIcon } from "@/components/Icons/ResearchInstitutes.tsx"
|
import { ResearchInstitutesIcon } from "@/components/Icons/ResearchInstitutes.tsx"
|
||||||
import { NSDCIcon } from "@/components/Icons/NSDC.tsx"
|
import { NSDCIcon } from "@/components/Icons/NSDC.tsx"
|
||||||
|
import { useIodPlaygroundContext } from "@/components/Option/Playground/PlaygroundIod.tsx"
|
||||||
|
|
||||||
const rotate = keyframes`
|
const rotate = keyframes`
|
||||||
0% {
|
0% {
|
||||||
@ -32,8 +33,8 @@ const breathe = keyframes`
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
// 花瓣
|
// 花瓣 /* ${(props) => (props.playing ? "running" : "paused")}; */
|
||||||
const CircleElement = styled.div<{ delay: number; playing: boolean }>`
|
const CircleElement = styled.div<{ delay: number }>`
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 300px;
|
width: 300px;
|
||||||
height: 160px;
|
height: 160px;
|
||||||
@ -46,7 +47,7 @@ const CircleElement = styled.div<{ delay: number; playing: boolean }>`
|
|||||||
${rotate} 6s linear infinite,
|
${rotate} 6s linear infinite,
|
||||||
${breathe} 2s infinite alternate;
|
${breathe} 2s infinite alternate;
|
||||||
animation-delay: ${(props) => props.delay}s;
|
animation-delay: ${(props) => props.delay}s;
|
||||||
animation-play-state: ${(props) => (props.playing ? "running" : "paused")};
|
animation-play-state: running;
|
||||||
animation-duration: 3s; /* 添加动画总持续时间 */
|
animation-duration: 3s; /* 添加动画总持续时间 */
|
||||||
animation-fill-mode: forwards; /* 保持动画结束时的状态 */
|
animation-fill-mode: forwards; /* 保持动画结束时的状态 */
|
||||||
`
|
`
|
||||||
@ -221,24 +222,19 @@ type Props = {
|
|||||||
className?: string
|
className?: string
|
||||||
}
|
}
|
||||||
export const PlaygroundIodRelevant: React.FC<Props> = ({ className }) => {
|
export const PlaygroundIodRelevant: React.FC<Props> = ({ className }) => {
|
||||||
const { messages, iodLoading, currentMessageId, iodSearch } =
|
const { iodLoading, iodSearch } = useMessageOption()
|
||||||
useMessageOption()
|
|
||||||
|
const { currentIodMessage } = useIodPlaygroundContext()
|
||||||
|
|
||||||
const showSearchData = useMemo(() => {
|
const showSearchData = useMemo(() => {
|
||||||
return iodSearch && messages.length > 0 && !iodLoading
|
return currentIodMessage && !iodLoading
|
||||||
}, [iodSearch, messages, iodLoading])
|
}, [currentIodMessage, iodLoading])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const data = useMemo(() => {
|
const data = useMemo(() => {
|
||||||
const currentMessage = messages?.find(
|
const loading = iodSearch && iodLoading
|
||||||
(message) => message.id === currentMessageId
|
const text = loading ? "正" : "已"
|
||||||
)
|
const text2 = loading ? "进行" : "完成"
|
||||||
|
const text3 = loading ? "……" : ""
|
||||||
const loading = (iodSearch && iodLoading)
|
|
||||||
const text = loading ? '正' : '已'
|
|
||||||
const text2 = loading ? '进行' : '完成'
|
|
||||||
const text3 = loading ? '……' : ''
|
|
||||||
const duration = loading ? 2.5 : 0
|
const duration = loading ? 2.5 : 0
|
||||||
|
|
||||||
return [
|
return [
|
||||||
@ -256,7 +252,12 @@ export const PlaygroundIodRelevant: React.FC<Props> = ({ className }) => {
|
|||||||
</span>
|
</span>
|
||||||
高等院校的
|
高等院校的
|
||||||
<span className="text-[#f00000]">
|
<span className="text-[#f00000]">
|
||||||
<CountUp decimals={1} end={53.7} duration={duration} separator="," />
|
<CountUp
|
||||||
|
decimals={1}
|
||||||
|
end={53.7}
|
||||||
|
duration={duration}
|
||||||
|
separator=","
|
||||||
|
/>
|
||||||
万个
|
万个
|
||||||
</span>
|
</span>
|
||||||
科学数据集中{text2}搜索{text3}
|
科学数据集中{text2}搜索{text3}
|
||||||
@ -268,7 +269,7 @@ export const PlaygroundIodRelevant: React.FC<Props> = ({ className }) => {
|
|||||||
<span className="text-green-700">
|
<span className="text-green-700">
|
||||||
{" "}
|
{" "}
|
||||||
<CountUp
|
<CountUp
|
||||||
end={currentMessage?.iodSources.data.total ?? 0}
|
end={currentIodMessage?.data.total ?? 0}
|
||||||
duration={2.5}
|
duration={2.5}
|
||||||
separator=","
|
separator=","
|
||||||
/>
|
/>
|
||||||
@ -288,9 +289,14 @@ export const PlaygroundIodRelevant: React.FC<Props> = ({ className }) => {
|
|||||||
<CountUp end={138} duration={duration} separator="," />
|
<CountUp end={138} duration={duration} separator="," />
|
||||||
万篇
|
万篇
|
||||||
</span>
|
</span>
|
||||||
学术论文、
|
数据论文、
|
||||||
<span className="text-[#f00000]">
|
<span className="text-[#f00000]">
|
||||||
<CountUp end={18.3} decimals={1} duration={duration} separator="," />
|
<CountUp
|
||||||
|
end={18.3}
|
||||||
|
decimals={1}
|
||||||
|
duration={duration}
|
||||||
|
separator=","
|
||||||
|
/>
|
||||||
万个
|
万个
|
||||||
</span>
|
</span>
|
||||||
数据项目中{text2}搜索{text3}
|
数据项目中{text2}搜索{text3}
|
||||||
@ -302,7 +308,7 @@ export const PlaygroundIodRelevant: React.FC<Props> = ({ className }) => {
|
|||||||
<span className="text-green-700">
|
<span className="text-green-700">
|
||||||
{" "}
|
{" "}
|
||||||
<CountUp
|
<CountUp
|
||||||
end={currentMessage?.iodSources.scenario.total ?? 0}
|
end={currentIodMessage?.scenario.total ?? 0}
|
||||||
duration={2.5}
|
duration={2.5}
|
||||||
separator=","
|
separator=","
|
||||||
/>
|
/>
|
||||||
@ -324,7 +330,13 @@ export const PlaygroundIodRelevant: React.FC<Props> = ({ className }) => {
|
|||||||
高等院校和科研机构、
|
高等院校和科研机构、
|
||||||
<span className="text-[#f00000]">
|
<span className="text-[#f00000]">
|
||||||
{" "}
|
{" "}
|
||||||
<CountUp end={2.1} decimals={1} duration={duration} separator="," />万
|
<CountUp
|
||||||
|
end={2.1}
|
||||||
|
decimals={1}
|
||||||
|
duration={duration}
|
||||||
|
separator=","
|
||||||
|
/>
|
||||||
|
万
|
||||||
</span>
|
</span>
|
||||||
家科技型企业、
|
家科技型企业、
|
||||||
<span className="text-[#f00000]">
|
<span className="text-[#f00000]">
|
||||||
@ -340,7 +352,7 @@ export const PlaygroundIodRelevant: React.FC<Props> = ({ className }) => {
|
|||||||
<span className="text-green-700">
|
<span className="text-green-700">
|
||||||
{" "}
|
{" "}
|
||||||
<CountUp
|
<CountUp
|
||||||
end={currentMessage?.iodSources.organization.total ?? 0}
|
end={currentIodMessage?.organization.total ?? 0}
|
||||||
duration={2.5}
|
duration={2.5}
|
||||||
separator=","
|
separator=","
|
||||||
/>
|
/>
|
||||||
@ -353,7 +365,7 @@ export const PlaygroundIodRelevant: React.FC<Props> = ({ className }) => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}, [messages, iodLoading])
|
}, [showSearchData, iodLoading])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card
|
<Card
|
||||||
@ -365,9 +377,9 @@ export const PlaygroundIodRelevant: React.FC<Props> = ({ className }) => {
|
|||||||
<div
|
<div
|
||||||
className={`absolute inset-0 pointer-events-none z-0 overflow-hidden ${showSearchData ? "" : ""}`}>
|
className={`absolute inset-0 pointer-events-none z-0 overflow-hidden ${showSearchData ? "" : ""}`}>
|
||||||
<div className="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 w-64 h-64">
|
<div className="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 w-64 h-64">
|
||||||
<CircleElement delay={0} playing={true} />
|
<CircleElement delay={0} />
|
||||||
<CircleElement delay={1} playing={true} />
|
<CircleElement delay={1} />
|
||||||
<CircleElement delay={2} playing={true} />
|
<CircleElement delay={2} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -376,16 +388,14 @@ export const PlaygroundIodRelevant: React.FC<Props> = ({ className }) => {
|
|||||||
<h2 className="text-xl font-semibold text-[#1a3c87] flex justify-center items-center">
|
<h2 className="text-xl font-semibold text-[#1a3c87] flex justify-center items-center">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<SearchIcon />
|
<SearchIcon />
|
||||||
{messages.length > 0
|
{currentIodMessage ? "科创数联网深度搜索" : "科创数联网连接资源"}
|
||||||
? "科创数联网深度搜索"
|
|
||||||
: "科创数联网连接资源"}
|
|
||||||
</div>
|
</div>
|
||||||
{/*<button className="bg-[#2563eb1a] text-[#08307f] font-medium py-1 px-3 rounded-full text-sm hover:bg-[#2563eb1a] transition-colors float-right">*/}
|
{/*<button className="bg-[#2563eb1a] text-[#08307f] font-medium py-1 px-3 rounded-full text-sm hover:bg-[#2563eb1a] transition-colors float-right">*/}
|
||||||
{/* {data.length}个结果*/}
|
{/* {data.length}个结果*/}
|
||||||
{/*</button>*/}
|
{/*</button>*/}
|
||||||
</h2>
|
</h2>
|
||||||
<p className="text-sm text-[#1a3c87] mt-1 text-center">
|
<p className="text-sm text-[#1a3c87] mt-1 text-center">
|
||||||
{messages.length > 0
|
{currentIodMessage
|
||||||
? "下面是在科创数联网上进行深度搜索得到的相关数据、场景和团队"
|
? "下面是在科创数联网上进行深度搜索得到的相关数据、场景和团队"
|
||||||
: "下面是科创数联网连接的数据、场景和团队"}
|
: "下面是科创数联网连接的数据、场景和团队"}
|
||||||
</p>
|
</p>
|
||||||
@ -393,7 +403,7 @@ export const PlaygroundIodRelevant: React.FC<Props> = ({ className }) => {
|
|||||||
|
|
||||||
{/* Content */}
|
{/* Content */}
|
||||||
<div className="space-y-2 flex-1 overflow-y-auto">
|
<div className="space-y-2 flex-1 overflow-y-auto">
|
||||||
{messages.length ? (
|
{currentIodMessage ? (
|
||||||
<AnimatePresence mode="wait">
|
<AnimatePresence mode="wait">
|
||||||
<motion.div
|
<motion.div
|
||||||
key="search-results"
|
key="search-results"
|
||||||
@ -422,16 +432,16 @@ export const PlaygroundIodRelevant: React.FC<Props> = ({ className }) => {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<p
|
<div
|
||||||
className={`text-gray-700 ${showSearchData ? "text-sm" : "text-lg"}`}>
|
className={`text-gray-700 ${showSearchData ? "text-sm" : "text-lg"}`}>
|
||||||
{item.title}
|
{item.title}
|
||||||
</p>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{item.description && (
|
{item.description && (
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<p className="text-xs text-gray-500 mt-1 pl-7">
|
<div className="text-xs text-gray-500 mt-1 pl-7">
|
||||||
{item.description}
|
{item.description}
|
||||||
</p>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -25,8 +25,10 @@ import { GenerationInfo } from "./GenerationInfo"
|
|||||||
import { parseReasoning } from "@/libs/reasoning"
|
import { parseReasoning } from "@/libs/reasoning"
|
||||||
import { humanizeMilliseconds } from "@/utils/humanize-milliseconds"
|
import { humanizeMilliseconds } from "@/utils/humanize-milliseconds"
|
||||||
import { AllIodRegistryEntry } from "@/types/iod.ts"
|
import { AllIodRegistryEntry } from "@/types/iod.ts"
|
||||||
|
import { PiNetwork } from "react-icons/pi"
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
id?: string
|
||||||
message: string
|
message: string
|
||||||
message_type?: string
|
message_type?: string
|
||||||
hideCopy?: boolean
|
hideCopy?: boolean
|
||||||
@ -50,9 +52,11 @@ type Props = {
|
|||||||
generationInfo?: any
|
generationInfo?: any
|
||||||
isStreaming: boolean
|
isStreaming: boolean
|
||||||
reasoningTimeTaken?: number
|
reasoningTimeTaken?: number
|
||||||
|
iodSearch?: boolean
|
||||||
|
setCurrentMessageId: (id: string) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export const PlaygroundMessage = (props: Props) => {
|
export const PlaygroundMessage: React.FC<Props> = (props) => {
|
||||||
const [isBtnPressed, setIsBtnPressed] = React.useState(false)
|
const [isBtnPressed, setIsBtnPressed] = React.useState(false)
|
||||||
const [editMode, setEditMode] = React.useState(false)
|
const [editMode, setEditMode] = React.useState(false)
|
||||||
|
|
||||||
@ -258,6 +262,18 @@ export const PlaygroundMessage = (props: Props) => {
|
|||||||
)}
|
)}
|
||||||
{props.isBot && (
|
{props.isBot && (
|
||||||
<>
|
<>
|
||||||
|
{/*数联网搜索*/}
|
||||||
|
{props.iodSearch && (
|
||||||
|
<Tooltip title="数联网信息">
|
||||||
|
<button
|
||||||
|
onClick={() => props.setCurrentMessageId(props.id)}
|
||||||
|
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">
|
||||||
|
<PiNetwork className="w-3 h-3 text-gray-400 group-hover:text-gray-500" />
|
||||||
|
</button>
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
|
||||||
{!props.hideCopy && (
|
{!props.hideCopy && (
|
||||||
<Tooltip title={t("copyToClipboard")}>
|
<Tooltip title={t("copyToClipboard")}>
|
||||||
<button
|
<button
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React, { useEffect, useMemo, useState } from "react"
|
import React, { useMemo } from "react"
|
||||||
import { DataNavigation } from "@/components/Common/DataNavigation.tsx"
|
import { DataNavigation } from "@/components/Common/DataNavigation.tsx"
|
||||||
import { Card, Drawer, Skeleton } from "antd"
|
import { Card, Skeleton } from "antd"
|
||||||
import { IodRegistryEntry } from "@/types/iod.ts"
|
import { IodRegistryEntry } from "@/types/iod.ts"
|
||||||
import { useIodPlaygroundContext } from "@/components/Option/Playground/PlaygroundIod.tsx"
|
import { useIodPlaygroundContext } from "@/components/Option/Playground/PlaygroundIod.tsx"
|
||||||
|
|
||||||
@ -33,7 +33,11 @@ type HeaderProps = {
|
|||||||
showButton?: boolean
|
showButton?: boolean
|
||||||
onClick?: () => void
|
onClick?: () => void
|
||||||
}
|
}
|
||||||
const Header: React.FC<HeaderProps> = ({ title, showButton = true, onClick }) => (
|
const Header: React.FC<HeaderProps> = ({
|
||||||
|
title,
|
||||||
|
showButton = true,
|
||||||
|
onClick
|
||||||
|
}) => (
|
||||||
<DataNavigation
|
<DataNavigation
|
||||||
Header={
|
Header={
|
||||||
<div className="flex items-center text-[#4ab01a] gap-1">
|
<div className="flex items-center text-[#4ab01a] gap-1">
|
||||||
@ -97,36 +101,28 @@ const Main: React.FC<MainProps> = ({ data, loading, truncate = true }) => (
|
|||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
className?: string
|
className?: string
|
||||||
}
|
}
|
||||||
export const PlaygroundScene: React.FC<Props> = ({ className }) => {
|
export const PlaygroundScene: React.FC<Props> = ({ className }) => {
|
||||||
const { messages, iodLoading, currentMessageId, iodSearch } =
|
const { iodLoading } = useMessageOption()
|
||||||
useMessageOption()
|
|
||||||
|
|
||||||
const { setShowPlayground, setDetailHeader, setDetailMain } =
|
const {
|
||||||
useIodPlaygroundContext()
|
setShowPlayground,
|
||||||
|
setDetailHeader,
|
||||||
|
setDetailMain,
|
||||||
|
currentIodMessage
|
||||||
|
} = useIodPlaygroundContext()
|
||||||
|
|
||||||
const data = useMemo<IodRegistryEntry[]>(() => {
|
const data = useMemo<IodRegistryEntry[]>(() => {
|
||||||
// 确保loading状态时数据大于3
|
return currentIodMessage
|
||||||
if (iodLoading) {
|
? currentIodMessage.scenario?.data ?? []
|
||||||
return defaultData
|
: defaultData
|
||||||
}
|
}, [currentIodMessage])
|
||||||
|
|
||||||
if (messages.length && iodSearch) {
|
|
||||||
const currentMessage = messages?.find(
|
|
||||||
(message) => message.id === currentMessageId
|
|
||||||
)
|
|
||||||
return currentMessage?.iodSources.scenario.data ?? []
|
|
||||||
}
|
|
||||||
|
|
||||||
return defaultData
|
|
||||||
}, [currentMessageId, messages, iodLoading])
|
|
||||||
|
|
||||||
const title = useMemo(() => {
|
const title = useMemo(() => {
|
||||||
return messages.length > 0 ? "推荐场景" : "热点场景"
|
return currentIodMessage ? "推荐场景" : "热点场景"
|
||||||
}, [messages])
|
}, [currentIodMessage])
|
||||||
|
|
||||||
const showMore = () => {
|
const showMore = () => {
|
||||||
setShowPlayground(false)
|
setShowPlayground(false)
|
||||||
@ -137,19 +133,17 @@ export const PlaygroundScene: React.FC<Props> = ({ className }) => {
|
|||||||
onClick={() => setShowPlayground(false)}
|
onClick={() => setShowPlayground(false)}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
setDetailMain(<Main loading={iodLoading} data={data} truncate={false} />)
|
setDetailMain(<Main loading={iodLoading && Boolean(currentIodMessage)} data={data} truncate={false} />)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card
|
<Card className={`${className}`} hoverable>
|
||||||
className={`${className}`}
|
|
||||||
hoverable>
|
|
||||||
<div className="h-full flex flex-col gap-2 relative">
|
<div className="h-full flex flex-col gap-2 relative">
|
||||||
{/* 数据导航 */}
|
{/* 数据导航 */}
|
||||||
<Header title={title} onClick={showMore} />
|
<Header title={title} onClick={showMore} />
|
||||||
|
|
||||||
{/* 数据列表 */}
|
{/* 数据列表 */}
|
||||||
<Main loading={iodLoading} data={data.slice(0, 3)} />
|
<Main loading={iodLoading && Boolean(currentIodMessage)} data={data.slice(0, 3)} />
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
)
|
)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React, { useEffect, useMemo } from "react"
|
import React, { useMemo } from "react"
|
||||||
import { DataNavigation } from "@/components/Common/DataNavigation.tsx"
|
import { DataNavigation } from "@/components/Common/DataNavigation.tsx"
|
||||||
import { Card, Skeleton } from "antd"
|
import { Card, Skeleton } from "antd"
|
||||||
import { IodRegistryEntry } from "@/types/iod.ts"
|
import { IodRegistryEntry } from "@/types/iod.ts"
|
||||||
@ -17,11 +17,10 @@ const defaultData: IodRegistryEntry[] = [
|
|||||||
doId: "91320507MAEKWL5Y2L"
|
doId: "91320507MAEKWL5Y2L"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
||||||
name: "伊利诺伊大学香槟分校(UIUC)",
|
name: "伊利诺伊大学香槟分校(UIUC)",
|
||||||
description: "创建于1867年,坐落于伊利诺伊州双子城厄巴纳–香槟市,",
|
description: "创建于1867年,坐落于伊利诺伊州双子城厄巴纳–香槟市,",
|
||||||
doId: "bdware.org/uiuc",
|
doId: "bdware.org/uiuc"
|
||||||
},
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
type HeaderProps = {
|
type HeaderProps = {
|
||||||
@ -113,31 +112,24 @@ type Props = {
|
|||||||
className?: string
|
className?: string
|
||||||
}
|
}
|
||||||
export const PlaygroundTeam: React.FC<Props> = ({ className }) => {
|
export const PlaygroundTeam: React.FC<Props> = ({ className }) => {
|
||||||
const { messages, iodLoading, currentMessageId, iodSearch } =
|
const { iodLoading } = useMessageOption()
|
||||||
useMessageOption()
|
|
||||||
|
|
||||||
const { setShowPlayground, setDetailHeader, setDetailMain } =
|
const {
|
||||||
useIodPlaygroundContext()
|
setShowPlayground,
|
||||||
|
setDetailHeader,
|
||||||
|
setDetailMain,
|
||||||
|
currentIodMessage
|
||||||
|
} = useIodPlaygroundContext()
|
||||||
|
|
||||||
const data = useMemo<IodRegistryEntry[]>(() => {
|
const data = useMemo<IodRegistryEntry[]>(() => {
|
||||||
// 确保loading状态时数据大于3
|
return currentIodMessage
|
||||||
if (iodLoading) {
|
? currentIodMessage.organization?.data ?? []
|
||||||
return defaultData
|
: defaultData
|
||||||
}
|
}, [currentIodMessage])
|
||||||
|
|
||||||
if (messages.length && iodSearch) {
|
|
||||||
const currentMessage = messages?.find(
|
|
||||||
(message) => message.id === currentMessageId
|
|
||||||
)
|
|
||||||
return currentMessage?.iodSources.organization.data ?? []
|
|
||||||
}
|
|
||||||
|
|
||||||
return defaultData
|
|
||||||
}, [currentMessageId, messages, iodLoading])
|
|
||||||
|
|
||||||
const title = useMemo(() => {
|
const title = useMemo(() => {
|
||||||
return messages.length > 0 ? "推荐团队" : "热点团队"
|
return currentIodMessage ? "推荐团队" : "热点团队"
|
||||||
}, [messages])
|
}, [currentIodMessage])
|
||||||
|
|
||||||
const showMore = () => {
|
const showMore = () => {
|
||||||
setShowPlayground(false)
|
setShowPlayground(false)
|
||||||
@ -148,17 +140,18 @@ export const PlaygroundTeam: React.FC<Props> = ({ className }) => {
|
|||||||
onClick={() => setShowPlayground(false)}
|
onClick={() => setShowPlayground(false)}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
setDetailMain(<Main loading={iodLoading} data={data} truncate={false} flat={false} />)
|
setDetailMain(
|
||||||
|
<Main loading={iodLoading && Boolean(currentIodMessage)} data={data} truncate={false} flat={false} />
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className={`${className}`} hoverable>
|
<Card className={`${className}`} hoverable>
|
||||||
<div className="h-full flex flex-col gap-2 relative">
|
<div className="h-full flex flex-col gap-2 relative">
|
||||||
{/* 数据导航 */}
|
{/* 数据导航 */}
|
||||||
<Header title={title} onClick={showMore} />
|
<Header title={title} onClick={showMore} />
|
||||||
{/* 数据列表 */}
|
{/* 数据列表 */}
|
||||||
<Main loading={iodLoading} data={data.slice(0, 3)} />
|
<Main loading={iodLoading && Boolean(currentIodMessage)} data={data.slice(0, 3)} />
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
)
|
)
|
||||||
|
@ -1,15 +1,13 @@
|
|||||||
import { Form, Image, Input, Modal, Tooltip, message } from "antd"
|
import { Form, Image, Input, message, Modal } from "antd"
|
||||||
import { Share } from "lucide-react"
|
|
||||||
import { useState } from "react"
|
|
||||||
import type { Message } from "~/store/option"
|
|
||||||
import Markdown from "./Markdown"
|
|
||||||
import React from "react"
|
import React from "react"
|
||||||
|
import Markdown from "./Markdown"
|
||||||
import { useMutation } from "@tanstack/react-query"
|
import { useMutation } from "@tanstack/react-query"
|
||||||
import { getPageShareUrl } from "~/services/ollama"
|
import { getPageShareUrl } from "~/services/ollama"
|
||||||
import { cleanUrl } from "~/libs/clean-url"
|
import { cleanUrl } from "~/libs/clean-url"
|
||||||
import { getTitleById, getUserId, saveWebshare } from "@/db"
|
import { getTitleById, getUserId, saveWebshare } from "@/db"
|
||||||
import { useTranslation } from "react-i18next"
|
import { useTranslation } from "react-i18next"
|
||||||
import fetcher from "@/libs/fetcher"
|
import fetcher from "@/libs/fetcher"
|
||||||
|
import { Message } from "@/types/message.ts"
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
messages: Message[]
|
messages: Message[]
|
||||||
|
@ -11,7 +11,8 @@ export const PlaygroundChat = () => {
|
|||||||
regenerateLastMessage,
|
regenerateLastMessage,
|
||||||
isSearchingInternet,
|
isSearchingInternet,
|
||||||
editMessage,
|
editMessage,
|
||||||
ttsEnabled
|
ttsEnabled,
|
||||||
|
setCurrentMessageId,
|
||||||
} = useMessageOption()
|
} = useMessageOption()
|
||||||
const [isSourceOpen, setIsSourceOpen] = React.useState(false)
|
const [isSourceOpen, setIsSourceOpen] = React.useState(false)
|
||||||
const [source, setSource] = React.useState<any>(null)
|
const [source, setSource] = React.useState<any>(null)
|
||||||
@ -27,6 +28,7 @@ export const PlaygroundChat = () => {
|
|||||||
{messages.map((message, index) => (
|
{messages.map((message, index) => (
|
||||||
<PlaygroundMessage
|
<PlaygroundMessage
|
||||||
key={index}
|
key={index}
|
||||||
|
id={message.id}
|
||||||
isBot={message.isBot}
|
isBot={message.isBot}
|
||||||
message={message.message}
|
message={message.message}
|
||||||
name={message.name}
|
name={message.name}
|
||||||
@ -49,6 +51,8 @@ export const PlaygroundChat = () => {
|
|||||||
generationInfo={message?.generationInfo}
|
generationInfo={message?.generationInfo}
|
||||||
isStreaming={streaming}
|
isStreaming={streaming}
|
||||||
reasoningTimeTaken={message?.reasoning_time_taken}
|
reasoningTimeTaken={message?.reasoning_time_taken}
|
||||||
|
setCurrentMessageId={setCurrentMessageId}
|
||||||
|
iodSearch={message.iodSearch}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
@ -218,7 +218,7 @@ export const PlaygroundForm = ({ dropedFile }: Props) => {
|
|||||||
{
|
{
|
||||||
key: 0,
|
key: 0,
|
||||||
label: (
|
label: (
|
||||||
<p
|
<div
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setIodSearch(true)
|
setIodSearch(true)
|
||||||
}}>
|
}}>
|
||||||
@ -227,13 +227,13 @@ export const PlaygroundForm = ({ dropedFile }: Props) => {
|
|||||||
<PiNetwork className="h-5 w-5" />开
|
<PiNetwork className="h-5 w-5" />开
|
||||||
</p>
|
</p>
|
||||||
<p className="text-[#00000080]">输出带数联网的回答</p>
|
<p className="text-[#00000080]">输出带数联网的回答</p>
|
||||||
</p>
|
</div>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 1,
|
key: 1,
|
||||||
label: (
|
label: (
|
||||||
<p
|
<div
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setIodSearch(false)
|
setIodSearch(false)
|
||||||
}}>
|
}}>
|
||||||
@ -242,7 +242,7 @@ export const PlaygroundForm = ({ dropedFile }: Props) => {
|
|||||||
<PiNetwork className="h-5 w-5" /> 关闭
|
<PiNetwork className="h-5 w-5" /> 关闭
|
||||||
</p>
|
</p>
|
||||||
<p className="text-[#00000080]">快速直接回答</p>
|
<p className="text-[#00000080]">快速直接回答</p>
|
||||||
</p>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -397,7 +397,7 @@ export const PlaygroundForm = ({ dropedFile }: Props) => {
|
|||||||
className={`!px-[5px] flex items-center justify-center dark:text-gray-300 ${
|
className={`!px-[5px] flex items-center justify-center dark:text-gray-300 ${
|
||||||
chatMode === "rag" ? "hidden" : "block"
|
chatMode === "rag" ? "hidden" : "block"
|
||||||
}`}>
|
}`}>
|
||||||
<ImageIcon stroke-width={1} className="h-5 w-5" />
|
<ImageIcon strokeWidth={1} className="h-5 w-5" />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
@ -420,12 +420,12 @@ export const PlaygroundForm = ({ dropedFile }: Props) => {
|
|||||||
}}
|
}}
|
||||||
className={`flex items-center justify-center dark:text-gray-300 !px-[5px]`}>
|
className={`flex items-center justify-center dark:text-gray-300 !px-[5px]`}>
|
||||||
{!isListening ? (
|
{!isListening ? (
|
||||||
<MicIcon stroke-width={1} className="h-5 w-5" />
|
<MicIcon strokeWidth={1} className="h-5 w-5" />
|
||||||
) : (
|
) : (
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<span className="animate-ping absolute inline-flex h-3 w-3 rounded-full bg-red-400 opacity-75"></span>
|
<span className="animate-ping absolute inline-flex h-3 w-3 rounded-full bg-red-400 opacity-75"></span>
|
||||||
<MicIcon
|
<MicIcon
|
||||||
stroke-width={1}
|
strokeWidth={1}
|
||||||
className="h-5 w-5"
|
className="h-5 w-5"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -9,7 +9,7 @@ import { PlaygroundTeam } from "@/components/Common/Playground/Team.tsx"
|
|||||||
import { Card } from "antd"
|
import { Card } from "antd"
|
||||||
import { CloseOutlined } from "@ant-design/icons"
|
import { CloseOutlined } from "@ant-design/icons"
|
||||||
import { useMessageOption } from "@/hooks/useMessageOption.tsx"
|
import { useMessageOption } from "@/hooks/useMessageOption.tsx"
|
||||||
import { Message } from "@/types/message.ts"
|
import { AllIodRegistryEntry } from "@/types/iod.ts"
|
||||||
|
|
||||||
// 定义 Context 类型
|
// 定义 Context 类型
|
||||||
interface IodPlaygroundContextType {
|
interface IodPlaygroundContextType {
|
||||||
@ -19,7 +19,7 @@ interface IodPlaygroundContextType {
|
|||||||
setDetailHeader: React.Dispatch<React.SetStateAction<React.ReactNode>>
|
setDetailHeader: React.Dispatch<React.SetStateAction<React.ReactNode>>
|
||||||
detailMain: React.ReactNode
|
detailMain: React.ReactNode
|
||||||
setDetailMain: React.Dispatch<React.SetStateAction<React.ReactNode>>
|
setDetailMain: React.Dispatch<React.SetStateAction<React.ReactNode>>
|
||||||
currentIodMessage: Message | null
|
currentIodMessage?: AllIodRegistryEntry
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建 Context
|
// 创建 Context
|
||||||
@ -41,36 +41,34 @@ export const useIodPlaygroundContext = () => {
|
|||||||
const PlaygroundIodProvider: React.FC<{ children: React.ReactNode }> = ({
|
const PlaygroundIodProvider: React.FC<{ children: React.ReactNode }> = ({
|
||||||
children
|
children
|
||||||
}) => {
|
}) => {
|
||||||
const { messages, iodLoading, currentMessageId, iodSearch } =
|
const { messages, iodLoading, currentMessageId } = useMessageOption()
|
||||||
useMessageOption()
|
|
||||||
|
|
||||||
const [showPlayground, setShowPlayground] = useState<boolean>(true)
|
const [showPlayground, setShowPlayground] = useState<boolean>(true)
|
||||||
const [detailHeader, setDetailHeader] = useState(<></>)
|
const [detailHeader, setDetailHeader] = useState(<></>)
|
||||||
const [detailMain, setDetailMain] = useState(<></>)
|
const [detailMain, setDetailMain] = useState(<></>)
|
||||||
|
|
||||||
const currentIodMessage = useMemo<Message | null>(() => {
|
const currentIodMessage = useMemo<AllIodRegistryEntry | undefined>(() => {
|
||||||
if (iodLoading) {
|
console.log('messages', messages)
|
||||||
return null
|
console.log("currentMessageId", currentMessageId)
|
||||||
|
console.log("iodLoading", iodLoading)
|
||||||
|
// loading 返回 undefined是为了避免,数据不足三个的情况
|
||||||
|
if (iodLoading || !messages.length) {
|
||||||
|
return undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
if (messages.length && iodSearch) {
|
// 如果不存在currentMessageId默认返回最后一个message
|
||||||
// 如果不存在currentMessageId默认返回最后一个message
|
if (!currentMessageId) {
|
||||||
if (!currentMessageId) {
|
const lastMessage = messages.at(-1)
|
||||||
return messages.at(-1)
|
// 如果最后一次message没有开启数联网搜索,则返回undefined
|
||||||
}
|
return lastMessage?.iodSearch ? lastMessage.iodSources : undefined
|
||||||
|
|
||||||
const currentMessage = messages?.find(
|
|
||||||
(message) => message.id === currentMessageId
|
|
||||||
)
|
|
||||||
if (currentMessage) {
|
|
||||||
return currentMessage
|
|
||||||
}
|
|
||||||
// 如果当前message不存在最后一个message
|
|
||||||
return messages.at(-1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null
|
const currentMessage = messages?.find(
|
||||||
}, [currentMessageId, messages, iodLoading, iodSearch])
|
(message) => message.id === currentMessageId
|
||||||
|
)
|
||||||
|
console.log("currentMessage", currentMessage)
|
||||||
|
return currentMessage?.iodSearch ? currentMessage.iodSources : undefined
|
||||||
|
}, [currentMessageId, messages, iodLoading])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PlaygroundContext.Provider
|
<PlaygroundContext.Provider
|
||||||
@ -154,7 +152,6 @@ const PlaygroundContent = () => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export const PlaygroundIod = () => {
|
export const PlaygroundIod = () => {
|
||||||
return (
|
return (
|
||||||
<div className="w-[36%] h-full pt-16 pr-5 pb-0">
|
<div className="w-[36%] h-full pt-16 pr-5 pb-0">
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
import { PencilIcon } from "lucide-react"
|
|
||||||
import { useMessage } from "../../../hooks/useMessage"
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
|
|
||||||
export const PlaygroundNewChat = () => {
|
|
||||||
const { setHistory, setMessages, setHistoryId } = useMessage()
|
|
||||||
const { t } = useTranslation('optionChat')
|
|
||||||
|
|
||||||
const handleClick = () => {
|
|
||||||
setHistoryId(null)
|
|
||||||
setMessages([])
|
|
||||||
setHistory([])
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<button
|
|
||||||
onClick={handleClick}
|
|
||||||
className="flex w-full border bg-transparent hover:bg-gray-200 dark:hover:bg-gray-800 text-gray-600 dark:text-gray-400 hover:text-gray-800 dark:hover:text-gray-200 focus:outline-none focus:ring-2 focus:ring-gray-500 focus:ring-offset-2 focus:ring-offset-gray-100 rounded-md p-2 dark:border-gray-800">
|
|
||||||
<PencilIcon className="mx-3 h-5 w-5" aria-hidden="true" />
|
|
||||||
<span className="inline-flex font-semibol text-white text-sm">
|
|
||||||
{t('newChat')}
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
)
|
|
||||||
}
|
|
@ -1,41 +1,20 @@
|
|||||||
import { useTranslation } from "react-i18next"
|
import { useTranslation } from "react-i18next"
|
||||||
import TextArea from "antd/es/input/TextArea"
|
import TextArea from "antd/es/input/TextArea"
|
||||||
import { useEffect, useState } from "react"
|
import { IodDb } from "@/db/iod.ts"
|
||||||
|
import { useState } from "react"
|
||||||
|
|
||||||
|
|
||||||
export const IodApp = () => {
|
export const IodApp = () => {
|
||||||
const { t } = useTranslation("settings")
|
const { t } = useTranslation("settings")
|
||||||
|
|
||||||
|
const db = IodDb.getInstance()
|
||||||
|
|
||||||
const [connectVal, setConnectVal] = useState<string>('')
|
const [connection, setConnection] = useState(JSON.stringify(db.getIodConnection(), null, 2))
|
||||||
|
|
||||||
const setConnectValWrap = (val: string) => {
|
const setConnectValWrap = (val: string) => {
|
||||||
localStorage.setItem("iod-connect", val)
|
db.insertIodConnection(JSON.parse(val))
|
||||||
setConnectVal(val)
|
setConnection(val)
|
||||||
}
|
}
|
||||||
useEffect(() => {
|
|
||||||
const val = localStorage.getItem("iod-connect")
|
|
||||||
const defaultVal = {
|
|
||||||
gatewayUrl: "tcp://reg01.public.internetofdata.cn:21037",
|
|
||||||
registry: "data/Registry",
|
|
||||||
localRepository: "data/Repository",
|
|
||||||
doBrowser: "http://021.node.internetapi.cn:21030/SCIDE/SCManager"
|
|
||||||
}
|
|
||||||
if (!val) {
|
|
||||||
localStorage.setItem(
|
|
||||||
"iod-connect",
|
|
||||||
JSON.stringify(defaultVal)
|
|
||||||
)
|
|
||||||
setConnectVal(JSON.stringify(defaultVal, null, 2))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const val = localStorage.getItem("iod-connect")
|
|
||||||
setConnectVal(JSON.stringify(JSON.parse(val), null, 2))
|
|
||||||
} catch (e) {
|
|
||||||
setConnectVal(JSON.stringify(defaultVal, null, 2))
|
|
||||||
}
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<dl className="flex flex-col space-y-6 text-sm">
|
<dl className="flex flex-col space-y-6 text-sm">
|
||||||
@ -47,7 +26,7 @@ export const IodApp = () => {
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col gap-3">
|
<div className="flex flex-col gap-3">
|
||||||
<span className="text-gray-700 dark:text-neutral-50">连接配置</span>
|
<span className="text-gray-700 dark:text-neutral-50">连接配置</span>
|
||||||
<TextArea rows={6} placeholder="请输入数联网连接配置" value={connectVal} onChange={(e) => setConnectValWrap(e.target.value)} />
|
<TextArea rows={6} placeholder="请输入数联网连接配置" value={connection} onChange={(e) => setConnectValWrap(e.target.value)} />
|
||||||
</div>
|
</div>
|
||||||
</dl>
|
</dl>
|
||||||
)
|
)
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import {
|
import { type ChatHistory as ChatHistoryType } from "~/store/option"
|
||||||
type ChatHistory as ChatHistoryType,
|
|
||||||
type Message as MessageType
|
|
||||||
} from "~/store/option"
|
|
||||||
import { AllIodRegistryEntry } from "@/types/iod.ts"
|
import { AllIodRegistryEntry } from "@/types/iod.ts"
|
||||||
|
import { type Message as MessageType } from "@/types/message.ts"
|
||||||
|
import { getDefaultIodSources } from "@/libs/iod.ts"
|
||||||
|
|
||||||
type HistoryInfo = {
|
type HistoryInfo = {
|
||||||
id: string
|
id: string
|
||||||
@ -249,38 +248,31 @@ export const saveHistory = async (
|
|||||||
await db.addChatHistory(history)
|
await db.addChatHistory(history)
|
||||||
return history
|
return history
|
||||||
}
|
}
|
||||||
|
export type HistoryMessage = {
|
||||||
export const saveMessage = async (
|
history_id: string
|
||||||
history_id: string,
|
name: string
|
||||||
name: string,
|
role: string
|
||||||
role: string,
|
content: string
|
||||||
content: string,
|
images: string[]
|
||||||
images: string[],
|
iodSearch?: boolean
|
||||||
webSources?: any[],
|
webSearch?: boolean
|
||||||
iodSources?: AllIodRegistryEntry,
|
webSources?: any[]
|
||||||
time?: number,
|
iodSources?: AllIodRegistryEntry
|
||||||
message_type?: string,
|
createdAt?: number
|
||||||
generationInfo?: any,
|
messageType?: string
|
||||||
|
generationInfo?: any
|
||||||
reasoning_time_taken?: number
|
reasoning_time_taken?: number
|
||||||
) => {
|
}
|
||||||
|
export const saveMessage = async (msg: HistoryMessage): Promise<Message> => {
|
||||||
const id = generateID()
|
const id = generateID()
|
||||||
let createdAt = Date.now()
|
let createdAt = Date.now()
|
||||||
if (time) {
|
if (msg.createdAt) {
|
||||||
createdAt += time
|
createdAt += msg.createdAt
|
||||||
}
|
}
|
||||||
const message = {
|
const message = {
|
||||||
|
...msg,
|
||||||
id,
|
id,
|
||||||
history_id,
|
|
||||||
name,
|
|
||||||
role,
|
|
||||||
content,
|
|
||||||
images,
|
|
||||||
createdAt,
|
createdAt,
|
||||||
webSources,
|
|
||||||
iodSources,
|
|
||||||
messageType: message_type,
|
|
||||||
generationInfo: generationInfo,
|
|
||||||
reasoning_time_taken
|
|
||||||
}
|
}
|
||||||
const db = new PageAssitDatabase()
|
const db = new PageAssitDatabase()
|
||||||
await db.addMessage(message)
|
await db.addMessage(message)
|
||||||
@ -304,11 +296,12 @@ export const formatToMessage = (messages: MessageHistory): MessageType[] => {
|
|||||||
messages.sort((a, b) => a.createdAt - b.createdAt)
|
messages.sort((a, b) => a.createdAt - b.createdAt)
|
||||||
return messages.map((message) => {
|
return messages.map((message) => {
|
||||||
return {
|
return {
|
||||||
|
...message,
|
||||||
isBot: message.role === "assistant",
|
isBot: message.role === "assistant",
|
||||||
message: message.content,
|
message: message.content,
|
||||||
name: message.name,
|
name: message.name,
|
||||||
webSources: message?.webSources || [],
|
webSources: message?.webSources || [],
|
||||||
iodSources: message?.iodSources || { data: [], scenario: [], organization: []},
|
iodSources: message?.iodSources || getDefaultIodSources(),
|
||||||
images: message.images || [],
|
images: message.images || [],
|
||||||
generationInfo: message?.generationInfo,
|
generationInfo: message?.generationInfo,
|
||||||
reasoning_time_taken: message?.reasoning_time_taken
|
reasoning_time_taken: message?.reasoning_time_taken
|
||||||
|
74
src/db/iod.ts
Normal file
74
src/db/iod.ts
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
const iodConnection = "iodConnection-g3"
|
||||||
|
|
||||||
|
export const defaultIodConnectionConfig = {
|
||||||
|
gatewayUrl: "tcp://reg01.public.internetofdata.cn:21037",
|
||||||
|
registry: "data/Registry",
|
||||||
|
localRepository: "data/Repository",
|
||||||
|
doBrowser: "http://021.node.internetapi.cn:21030/SCIDE/SCManager"
|
||||||
|
} as const
|
||||||
|
|
||||||
|
export type IodConnectionConfig = {
|
||||||
|
gatewayUrl: string
|
||||||
|
registry: string
|
||||||
|
localRepository: string
|
||||||
|
doBrowser: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export class IodDb {
|
||||||
|
private static instance: IodDb
|
||||||
|
private static iodConnectionConfig: IodConnectionConfig | null = null
|
||||||
|
|
||||||
|
// 单例模式
|
||||||
|
static getInstance(): IodDb {
|
||||||
|
if (!IodDb.instance) {
|
||||||
|
IodDb.instance = new IodDb()
|
||||||
|
}
|
||||||
|
return IodDb.instance
|
||||||
|
}
|
||||||
|
|
||||||
|
insertIodConnection(config: IodConnectionConfig): void {
|
||||||
|
try {
|
||||||
|
localStorage.setItem(iodConnection, JSON.stringify(config))
|
||||||
|
IodDb.iodConnectionConfig = config
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to save IOD connection config:', error)
|
||||||
|
throw new Error('Failed to save IOD connection configuration')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getIodConnection(): IodConnectionConfig {
|
||||||
|
// 如果已经有缓存,直接返回
|
||||||
|
if (IodDb.iodConnectionConfig) {
|
||||||
|
return IodDb.iodConnectionConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const val = localStorage.getItem(iodConnection)
|
||||||
|
if (!val) {
|
||||||
|
return defaultIodConnectionConfig
|
||||||
|
}
|
||||||
|
IodDb.iodConnectionConfig = JSON.parse(val)
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('Failed to parse IOD connection config, using default:', error)
|
||||||
|
return defaultIodConnectionConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加清除配置的方法
|
||||||
|
clearIodConnection(): void {
|
||||||
|
try {
|
||||||
|
localStorage.removeItem(iodConnection)
|
||||||
|
IodDb.iodConnectionConfig = null
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to clear IOD connection config:', error)
|
||||||
|
throw new Error('Failed to clear IOD connection configuration')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getIodConfig() {
|
||||||
|
return {
|
||||||
|
connection: this.getIodConnection(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
import { saveHistory, saveMessage } from "@/db"
|
import { HistoryMessage, saveHistory, saveMessage } from "@/db"
|
||||||
import {
|
import {
|
||||||
setLastUsedChatModel,
|
setLastUsedChatModel,
|
||||||
setLastUsedChatSystemPrompt
|
setLastUsedChatSystemPrompt
|
||||||
@ -23,7 +23,9 @@ export const saveMessageOnError = async ({
|
|||||||
message_source = "web-ui",
|
message_source = "web-ui",
|
||||||
message_type,
|
message_type,
|
||||||
prompt_content,
|
prompt_content,
|
||||||
prompt_id
|
prompt_id,
|
||||||
|
iodSearch,
|
||||||
|
webSearch,
|
||||||
}: {
|
}: {
|
||||||
e: any
|
e: any
|
||||||
setHistory: (history: ChatHistory) => void
|
setHistory: (history: ChatHistory) => void
|
||||||
@ -38,7 +40,9 @@ export const saveMessageOnError = async ({
|
|||||||
message_source?: "copilot" | "web-ui"
|
message_source?: "copilot" | "web-ui"
|
||||||
message_type?: string
|
message_type?: string
|
||||||
prompt_id?: string
|
prompt_id?: string
|
||||||
prompt_content?: string
|
prompt_content?: string,
|
||||||
|
iodSearch?: boolean,
|
||||||
|
webSearch?: boolean,
|
||||||
}) => {
|
}) => {
|
||||||
if (
|
if (
|
||||||
e?.name === "AbortError" ||
|
e?.name === "AbortError" ||
|
||||||
@ -59,31 +63,31 @@ export const saveMessageOnError = async ({
|
|||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|
||||||
|
const defaultMessage: HistoryMessage = {
|
||||||
|
history_id: historyId,
|
||||||
|
name: selectedModel,
|
||||||
|
role: "assistant",
|
||||||
|
content: botMessage,
|
||||||
|
webSources: [],
|
||||||
|
iodSources: getDefaultIodSources(),
|
||||||
|
messageType: message_type,
|
||||||
|
iodSearch,
|
||||||
|
webSearch,
|
||||||
|
images: []
|
||||||
|
}
|
||||||
|
|
||||||
if (historyId) {
|
if (historyId) {
|
||||||
if (!isRegenerating) {
|
if (!isRegenerating) {
|
||||||
await saveMessage(
|
await saveMessage({
|
||||||
historyId,
|
...JSON.parse(JSON.stringify(defaultMessage)),
|
||||||
selectedModel,
|
role: "user",
|
||||||
"user",
|
content: userMessage,
|
||||||
userMessage,
|
images: [image]
|
||||||
[image],
|
})
|
||||||
[],
|
|
||||||
getDefaultIodSources(),
|
|
||||||
1,
|
|
||||||
message_type
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
await saveMessage(
|
await saveMessage({
|
||||||
historyId,
|
...JSON.parse(JSON.stringify(defaultMessage))
|
||||||
selectedModel,
|
})
|
||||||
"assistant",
|
|
||||||
botMessage,
|
|
||||||
[],
|
|
||||||
[],
|
|
||||||
getDefaultIodSources(),
|
|
||||||
2,
|
|
||||||
message_type
|
|
||||||
)
|
|
||||||
await setLastUsedChatModel(historyId, selectedModel)
|
await setLastUsedChatModel(historyId, selectedModel)
|
||||||
if (prompt_id || prompt_content) {
|
if (prompt_id || prompt_content) {
|
||||||
await setLastUsedChatSystemPrompt(historyId, {
|
await setLastUsedChatSystemPrompt(historyId, {
|
||||||
@ -95,28 +99,19 @@ export const saveMessageOnError = async ({
|
|||||||
const title = await generateTitle(selectedModel, userMessage, userMessage)
|
const title = await generateTitle(selectedModel, userMessage, userMessage)
|
||||||
const newHistoryId = await saveHistory(title, false, message_source)
|
const newHistoryId = await saveHistory(title, false, message_source)
|
||||||
if (!isRegenerating) {
|
if (!isRegenerating) {
|
||||||
await saveMessage(
|
await saveMessage({
|
||||||
newHistoryId.id,
|
...JSON.parse(JSON.stringify(defaultMessage)),
|
||||||
selectedModel,
|
history_id: newHistoryId.id,
|
||||||
"user",
|
content: userMessage,
|
||||||
userMessage,
|
role: "user",
|
||||||
[image],
|
images: [image]
|
||||||
[],
|
})
|
||||||
getDefaultIodSources(),
|
|
||||||
1,
|
|
||||||
message_type
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
await saveMessage(
|
await saveMessage(
|
||||||
newHistoryId.id,
|
{
|
||||||
selectedModel,
|
...JSON.parse(JSON.stringify(defaultMessage)),
|
||||||
"assistant",
|
history_id: newHistoryId.id,
|
||||||
botMessage,
|
},
|
||||||
[],
|
|
||||||
[],
|
|
||||||
getDefaultIodSources(),
|
|
||||||
2,
|
|
||||||
message_type
|
|
||||||
)
|
)
|
||||||
setHistoryId(newHistoryId.id)
|
setHistoryId(newHistoryId.id)
|
||||||
await setLastUsedChatModel(newHistoryId.id, selectedModel)
|
await setLastUsedChatModel(newHistoryId.id, selectedModel)
|
||||||
@ -142,6 +137,8 @@ export const saveMessageOnSuccess = async ({
|
|||||||
message,
|
message,
|
||||||
image,
|
image,
|
||||||
fullText,
|
fullText,
|
||||||
|
iodSearch,
|
||||||
|
webSearch,
|
||||||
webSources,
|
webSources,
|
||||||
iodSources,
|
iodSources,
|
||||||
message_source = "web-ui",
|
message_source = "web-ui",
|
||||||
@ -158,6 +155,8 @@ export const saveMessageOnSuccess = async ({
|
|||||||
message: string
|
message: string
|
||||||
image: string
|
image: string
|
||||||
fullText: string
|
fullText: string
|
||||||
|
iodSearch?: boolean
|
||||||
|
webSearch?: boolean
|
||||||
webSources: any[]
|
webSources: any[]
|
||||||
iodSources: AllIodRegistryEntry
|
iodSources: AllIodRegistryEntry
|
||||||
message_source?: "copilot" | "web-ui"
|
message_source?: "copilot" | "web-ui"
|
||||||
@ -168,34 +167,38 @@ export const saveMessageOnSuccess = async ({
|
|||||||
reasoning_time_taken?: number
|
reasoning_time_taken?: number
|
||||||
}) => {
|
}) => {
|
||||||
var botMessage
|
var botMessage
|
||||||
|
|
||||||
|
const defaultMessage: HistoryMessage = {
|
||||||
|
history_id: historyId,
|
||||||
|
name: selectedModel,
|
||||||
|
role: "assistant",
|
||||||
|
content: fullText,
|
||||||
|
webSources: webSources,
|
||||||
|
iodSources: iodSources,
|
||||||
|
messageType: message_type,
|
||||||
|
images: [],
|
||||||
|
iodSearch,
|
||||||
|
webSearch,
|
||||||
|
generationInfo,
|
||||||
|
reasoning_time_taken,
|
||||||
|
}
|
||||||
if (historyId) {
|
if (historyId) {
|
||||||
if (!isRegenerate) {
|
if (!isRegenerate) {
|
||||||
await saveMessage(
|
await saveMessage(
|
||||||
historyId,
|
{
|
||||||
selectedModel,
|
...JSON.parse(JSON.stringify(defaultMessage)),
|
||||||
"user",
|
role: "user",
|
||||||
message,
|
content: message,
|
||||||
[image],
|
images: [image],
|
||||||
[],
|
webSources: [],
|
||||||
getDefaultIodSources(),
|
iodSources: getDefaultIodSources(),
|
||||||
1,
|
},
|
||||||
message_type,
|
|
||||||
generationInfo,
|
|
||||||
reasoning_time_taken
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
botMessage = await saveMessage(
|
botMessage = await saveMessage(
|
||||||
historyId,
|
{
|
||||||
selectedModel!,
|
...JSON.parse(JSON.stringify(defaultMessage)),
|
||||||
"assistant",
|
}
|
||||||
fullText,
|
|
||||||
[],
|
|
||||||
webSources,
|
|
||||||
iodSources,
|
|
||||||
2,
|
|
||||||
message_type,
|
|
||||||
generationInfo,
|
|
||||||
reasoning_time_taken
|
|
||||||
)
|
)
|
||||||
updateDialog(historyId, botMessage)
|
updateDialog(historyId, botMessage)
|
||||||
await setLastUsedChatModel(historyId, selectedModel!)
|
await setLastUsedChatModel(historyId, selectedModel!)
|
||||||
@ -209,30 +212,21 @@ export const saveMessageOnSuccess = async ({
|
|||||||
const title = await generateTitle(selectedModel, message, message)
|
const title = await generateTitle(selectedModel, message, message)
|
||||||
const newHistoryId = await saveHistory(title, false, message_source)
|
const newHistoryId = await saveHistory(title, false, message_source)
|
||||||
await saveMessage(
|
await saveMessage(
|
||||||
newHistoryId.id,
|
{
|
||||||
selectedModel,
|
...JSON.parse(JSON.stringify(defaultMessage)),
|
||||||
"user",
|
history_id: newHistoryId.id,
|
||||||
message,
|
role: "user",
|
||||||
[image],
|
content: message,
|
||||||
[],
|
images: [image],
|
||||||
getDefaultIodSources(),
|
webSources: [],
|
||||||
1,
|
iodSources: getDefaultIodSources(),
|
||||||
message_type,
|
},
|
||||||
generationInfo,
|
|
||||||
reasoning_time_taken
|
|
||||||
)
|
)
|
||||||
botMessage = await saveMessage(
|
botMessage = await saveMessage(
|
||||||
newHistoryId.id,
|
{
|
||||||
selectedModel!,
|
...JSON.parse(JSON.stringify(defaultMessage)),
|
||||||
"assistant",
|
history_id: newHistoryId.id,
|
||||||
fullText,
|
}
|
||||||
[],
|
|
||||||
webSources,
|
|
||||||
iodSources,
|
|
||||||
2,
|
|
||||||
message_type,
|
|
||||||
generationInfo,
|
|
||||||
reasoning_time_taken
|
|
||||||
)
|
)
|
||||||
updateDialog(newHistoryId.id, botMessage)
|
updateDialog(newHistoryId.id, botMessage)
|
||||||
setHistoryId(newHistoryId.id)
|
setHistoryId(newHistoryId.id)
|
||||||
|
@ -2,12 +2,12 @@ import React from "react"
|
|||||||
import { cleanUrl } from "~/libs/clean-url"
|
import { cleanUrl } from "~/libs/clean-url"
|
||||||
import {
|
import {
|
||||||
defaultEmbeddingModelForRag,
|
defaultEmbeddingModelForRag,
|
||||||
geWebSearchFollowUpPrompt,
|
|
||||||
getOllamaURL,
|
getOllamaURL,
|
||||||
|
geWebSearchFollowUpPrompt,
|
||||||
promptForRag,
|
promptForRag,
|
||||||
systemPromptForNonRag
|
systemPromptForNonRag
|
||||||
} from "~/services/ollama"
|
} from "~/services/ollama"
|
||||||
import { useStoreMessageOption, type Message } from "~/store/option"
|
import { useStoreMessageOption } from "~/store/option"
|
||||||
import { useStoreMessage } from "~/store"
|
import { useStoreMessage } from "~/store"
|
||||||
import { SystemMessage } from "@langchain/core/messages"
|
import { SystemMessage } from "@langchain/core/messages"
|
||||||
import { getDataFromCurrentTab } from "~/libs/get-html"
|
import { getDataFromCurrentTab } from "~/libs/get-html"
|
||||||
@ -43,6 +43,7 @@ import {
|
|||||||
} from "@/libs/reasoning"
|
} from "@/libs/reasoning"
|
||||||
import { AllIodRegistryEntry } from "@/types/iod.ts"
|
import { AllIodRegistryEntry } from "@/types/iod.ts"
|
||||||
import { getDefaultIodSources } from "@/libs/iod.ts"
|
import { getDefaultIodSources } from "@/libs/iod.ts"
|
||||||
|
import { Message } from "@/types/message.ts"
|
||||||
|
|
||||||
export const useMessage = () => {
|
export const useMessage = () => {
|
||||||
const {
|
const {
|
||||||
|
@ -7,7 +7,7 @@ import {
|
|||||||
promptForRag,
|
promptForRag,
|
||||||
systemPromptForNonRagOption
|
systemPromptForNonRagOption
|
||||||
} from "~/services/ollama"
|
} from "~/services/ollama"
|
||||||
import type { ChatHistory, Message, MeteringEntry } from "~/store/option"
|
import type { ChatHistory, MeteringEntry } from "~/store/option"
|
||||||
import { useStoreMessageOption } from "~/store/option"
|
import { useStoreMessageOption } from "~/store/option"
|
||||||
import { SystemMessage } from "@langchain/core/messages"
|
import { SystemMessage } from "@langchain/core/messages"
|
||||||
import {
|
import {
|
||||||
@ -47,6 +47,7 @@ import {
|
|||||||
removeReasoning
|
removeReasoning
|
||||||
} from "@/libs/reasoning"
|
} from "@/libs/reasoning"
|
||||||
import { getDefaultIodSources } from "@/libs/iod.ts"
|
import { getDefaultIodSources } from "@/libs/iod.ts"
|
||||||
|
import type { Message } from "@/types/message.ts"
|
||||||
|
|
||||||
export const useMessageOption = () => {
|
export const useMessageOption = () => {
|
||||||
const {
|
const {
|
||||||
@ -214,36 +215,39 @@ export const useMessageOption = () => {
|
|||||||
data: meter
|
data: meter
|
||||||
})
|
})
|
||||||
|
|
||||||
|
let defaultMessage: Message = {
|
||||||
|
isBot: true,
|
||||||
|
name: selectedModel,
|
||||||
|
message,
|
||||||
|
iodSearch,
|
||||||
|
webSearch,
|
||||||
|
webSources: [],
|
||||||
|
iodSources: getDefaultIodSources(),
|
||||||
|
images: [image]
|
||||||
|
}
|
||||||
|
|
||||||
if (!isRegenerate) {
|
if (!isRegenerate) {
|
||||||
newMessage = [
|
newMessage = [
|
||||||
...messages,
|
...messages,
|
||||||
{
|
{
|
||||||
|
...JSON.parse(JSON.stringify(defaultMessage)),
|
||||||
|
id: generateID(),
|
||||||
isBot: false,
|
isBot: false,
|
||||||
name: "You",
|
name: "You",
|
||||||
message,
|
|
||||||
webSources: [],
|
|
||||||
iodSources: getDefaultIodSources(),
|
|
||||||
images: [image]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
isBot: true,
|
...JSON.parse(JSON.stringify(defaultMessage)),
|
||||||
name: selectedModel,
|
id: generateMessageId,
|
||||||
message: "",
|
message: "",
|
||||||
webSources: [],
|
|
||||||
iodSources: getDefaultIodSources(),
|
|
||||||
id: generateMessageId
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
} else {
|
} else {
|
||||||
newMessage = [
|
newMessage = [
|
||||||
...messages,
|
...messages,
|
||||||
{
|
{
|
||||||
isBot: true,
|
...JSON.parse(JSON.stringify(defaultMessage)),
|
||||||
name: selectedModel,
|
id: generateMessageId,
|
||||||
message: "▋",
|
message: " ",
|
||||||
webSources: [],
|
|
||||||
iodSources: getDefaultIodSources(),
|
|
||||||
id: generateMessageId
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -525,6 +529,8 @@ export const useMessageOption = () => {
|
|||||||
message,
|
message,
|
||||||
image,
|
image,
|
||||||
fullText,
|
fullText,
|
||||||
|
iodSearch,
|
||||||
|
webSearch,
|
||||||
webSources,
|
webSources,
|
||||||
iodSources,
|
iodSources,
|
||||||
generationInfo,
|
generationInfo,
|
||||||
@ -566,7 +572,9 @@ export const useMessageOption = () => {
|
|||||||
setHistory,
|
setHistory,
|
||||||
setHistoryId,
|
setHistoryId,
|
||||||
userMessage: message,
|
userMessage: message,
|
||||||
isRegenerating: isRegenerate
|
isRegenerating: isRegenerate,
|
||||||
|
iodSearch,
|
||||||
|
webSearch,
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!errorSave) {
|
if (!errorSave) {
|
||||||
@ -672,6 +680,7 @@ export const useMessageOption = () => {
|
|||||||
|
|
||||||
let newMessage: Message[] = []
|
let newMessage: Message[] = []
|
||||||
let generateMessageId = generateID()
|
let generateMessageId = generateID()
|
||||||
|
setCurrentMessageId(generateMessageId)
|
||||||
const meter: MeteringEntry = {
|
const meter: MeteringEntry = {
|
||||||
id: generateMessageId,
|
id: generateMessageId,
|
||||||
queryContent: message,
|
queryContent: message,
|
||||||
@ -682,7 +691,6 @@ export const useMessageOption = () => {
|
|||||||
loading: true,
|
loading: true,
|
||||||
data: meter
|
data: meter
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!isRegenerate) {
|
if (!isRegenerate) {
|
||||||
newMessage = [
|
newMessage = [
|
||||||
...messages,
|
...messages,
|
||||||
@ -690,6 +698,7 @@ export const useMessageOption = () => {
|
|||||||
isBot: false,
|
isBot: false,
|
||||||
name: "You",
|
name: "You",
|
||||||
message,
|
message,
|
||||||
|
id: generateID(),
|
||||||
webSources: [],
|
webSources: [],
|
||||||
iodSources: getDefaultIodSources(),
|
iodSources: getDefaultIodSources(),
|
||||||
images: [image]
|
images: [image]
|
||||||
@ -889,7 +898,6 @@ export const useMessageOption = () => {
|
|||||||
content: fullText
|
content: fullText
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|
||||||
await saveMessageOnSuccess({
|
await saveMessageOnSuccess({
|
||||||
historyId,
|
historyId,
|
||||||
setHistoryId,
|
setHistoryId,
|
||||||
@ -898,6 +906,8 @@ export const useMessageOption = () => {
|
|||||||
message,
|
message,
|
||||||
image,
|
image,
|
||||||
fullText,
|
fullText,
|
||||||
|
iodSearch,
|
||||||
|
webSearch,
|
||||||
source: [],
|
source: [],
|
||||||
generationInfo,
|
generationInfo,
|
||||||
prompt_content: promptContent,
|
prompt_content: promptContent,
|
||||||
@ -914,8 +924,8 @@ export const useMessageOption = () => {
|
|||||||
const { cot, content } = responseResolver(fullText)
|
const { cot, content } = responseResolver(fullText)
|
||||||
const currentMeteringEntry = {
|
const currentMeteringEntry = {
|
||||||
...meter,
|
...meter,
|
||||||
modelInputTokenCount: prompt.length,
|
modelInputTokenCount: prompt? prompt.length : 0,
|
||||||
modelOutputTokenCount: fullText.length,
|
modelOutputTokenCount: fullText? fullText.length : 0,
|
||||||
model: ollama.modelName ?? ollama.model,
|
model: ollama.modelName ?? ollama.model,
|
||||||
relatedDataCount: 0,
|
relatedDataCount: 0,
|
||||||
timeTaken: new Date().getTime() - chatStartTime.getTime(),
|
timeTaken: new Date().getTime() - chatStartTime.getTime(),
|
||||||
@ -943,7 +953,9 @@ export const useMessageOption = () => {
|
|||||||
userMessage: message,
|
userMessage: message,
|
||||||
isRegenerating: isRegenerate,
|
isRegenerating: isRegenerate,
|
||||||
prompt_content: promptContent,
|
prompt_content: promptContent,
|
||||||
prompt_id: promptId
|
prompt_id: promptId,
|
||||||
|
iodSearch,
|
||||||
|
webSearch,
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!errorSave) {
|
if (!errorSave) {
|
||||||
@ -1274,7 +1286,9 @@ export const useMessageOption = () => {
|
|||||||
fullText,
|
fullText,
|
||||||
source,
|
source,
|
||||||
generationInfo,
|
generationInfo,
|
||||||
reasoning_time_taken: timetaken
|
reasoning_time_taken: timetaken,
|
||||||
|
iodSearch,
|
||||||
|
webSearch,
|
||||||
})
|
})
|
||||||
|
|
||||||
setIsProcessing(false)
|
setIsProcessing(false)
|
||||||
@ -1290,7 +1304,9 @@ export const useMessageOption = () => {
|
|||||||
setHistory,
|
setHistory,
|
||||||
setHistoryId,
|
setHistoryId,
|
||||||
userMessage: message,
|
userMessage: message,
|
||||||
isRegenerating: isRegenerate
|
isRegenerating: isRegenerate,
|
||||||
|
iodSearch,
|
||||||
|
webSearch,
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!errorSave) {
|
if (!errorSave) {
|
||||||
|
@ -6,6 +6,7 @@ import {
|
|||||||
} from "@/db"
|
} from "@/db"
|
||||||
import { exportKnowledge, importKnowledge } from "@/db/knowledge"
|
import { exportKnowledge, importKnowledge } from "@/db/knowledge"
|
||||||
import { exportVectors, importVectors } from "@/db/vector"
|
import { exportVectors, importVectors } from "@/db/vector"
|
||||||
|
import { IodDb } from "@/db/iod"
|
||||||
import { message } from "antd"
|
import { message } from "antd"
|
||||||
|
|
||||||
export const exportPageAssistData = async () => {
|
export const exportPageAssistData = async () => {
|
||||||
@ -13,12 +14,14 @@ export const exportPageAssistData = async () => {
|
|||||||
const chat = await exportChatHistory()
|
const chat = await exportChatHistory()
|
||||||
const vector = await exportVectors()
|
const vector = await exportVectors()
|
||||||
const prompts = await exportPrompts()
|
const prompts = await exportPrompts()
|
||||||
|
const iod = IodDb.getInstance().getIodConfig()
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
knowledge,
|
knowledge,
|
||||||
chat,
|
chat,
|
||||||
vector,
|
vector,
|
||||||
prompts
|
prompts,
|
||||||
|
iod
|
||||||
}
|
}
|
||||||
|
|
||||||
const dataStr = JSON.stringify(data)
|
const dataStr = JSON.stringify(data)
|
||||||
@ -34,6 +37,7 @@ export const exportPageAssistData = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const importPageAssistData = async (file: File) => {
|
export const importPageAssistData = async (file: File) => {
|
||||||
|
debugger
|
||||||
const reader = new FileReader()
|
const reader = new FileReader()
|
||||||
reader.onload = async () => {
|
reader.onload = async () => {
|
||||||
try {
|
try {
|
||||||
@ -55,6 +59,10 @@ export const importPageAssistData = async (file: File) => {
|
|||||||
await importPrompts(data.prompts)
|
await importPrompts(data.prompts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(data?.iod) {
|
||||||
|
IodDb.getInstance().insertIodConnection(data.iod)
|
||||||
|
}
|
||||||
|
|
||||||
message.success("Data imported successfully")
|
message.success("Data imported successfully")
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e)
|
console.error(e)
|
||||||
|
@ -1,28 +1,6 @@
|
|||||||
import { Knowledge } from "@/db/knowledge"
|
import { Knowledge } from "@/db/knowledge"
|
||||||
import { create } from "zustand"
|
import { create } from "zustand"
|
||||||
import { AllIodRegistryEntry } from "@/types/iod.ts"
|
import { Message } from "esbuild"
|
||||||
|
|
||||||
type WebSearch = {
|
|
||||||
search_engine: string
|
|
||||||
search_url: string
|
|
||||||
search_query: string
|
|
||||||
search_results: {
|
|
||||||
title: string
|
|
||||||
link: string
|
|
||||||
}[]
|
|
||||||
}
|
|
||||||
export type Message = {
|
|
||||||
isBot: boolean
|
|
||||||
name: string
|
|
||||||
message: string
|
|
||||||
webSources: any[]
|
|
||||||
iodSources: AllIodRegistryEntry
|
|
||||||
images?: string[]
|
|
||||||
search?: WebSearch
|
|
||||||
reasoning_time_taken?: number
|
|
||||||
id?: string
|
|
||||||
messageType?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ChatHistory = {
|
export type ChatHistory = {
|
||||||
role: "user" | "assistant" | "system"
|
role: "user" | "assistant" | "system"
|
||||||
@ -36,8 +14,11 @@ type State = {
|
|||||||
setMessages: (messages: Message[]) => void
|
setMessages: (messages: Message[]) => void
|
||||||
history: ChatHistory
|
history: ChatHistory
|
||||||
setHistory: (history: ChatHistory) => void
|
setHistory: (history: ChatHistory) => void
|
||||||
currentMeteringEntry: {data: MeteringEntry, loading: boolean}
|
currentMeteringEntry: { data: MeteringEntry; loading: boolean }
|
||||||
setCurrentMeteringEntry: (meteringEntry: {data: MeteringEntry, loading: boolean}) => void
|
setCurrentMeteringEntry: (meteringEntry: {
|
||||||
|
data: MeteringEntry
|
||||||
|
loading: boolean
|
||||||
|
}) => void
|
||||||
meteringEntries: MeteringEntry[]
|
meteringEntries: MeteringEntry[]
|
||||||
setMeteringEntries: (meteringEntries: MeteringEntry[]) => void
|
setMeteringEntries: (meteringEntries: MeteringEntry[]) => void
|
||||||
streaming: boolean
|
streaming: boolean
|
||||||
@ -123,9 +104,12 @@ export const useStoreMessageOption = create<State>((set) => ({
|
|||||||
setMessages: (messages) => set({ messages }),
|
setMessages: (messages) => set({ messages }),
|
||||||
history: [],
|
history: [],
|
||||||
setHistory: (history) => set({ history }),
|
setHistory: (history) => set({ history }),
|
||||||
currentMeteringEntry: {data: {} as MeteringEntry, loading: false},
|
currentMeteringEntry: { data: {} as MeteringEntry, loading: false },
|
||||||
setCurrentMeteringEntry: (currentMeteringEntry) => set({ currentMeteringEntry }),
|
setCurrentMeteringEntry: (currentMeteringEntry) =>
|
||||||
meteringEntries: JSON.parse(localStorage.getItem("meteringEntries") || JSON.stringify([])),
|
set({ currentMeteringEntry }),
|
||||||
|
meteringEntries: JSON.parse(
|
||||||
|
localStorage.getItem("meteringEntries") || JSON.stringify([])
|
||||||
|
),
|
||||||
setMeteringEntries: (meteringEntries) => set({ meteringEntries }),
|
setMeteringEntries: (meteringEntries) => set({ meteringEntries }),
|
||||||
streaming: false,
|
streaming: false,
|
||||||
setStreaming: (streaming) => set({ streaming }),
|
setStreaming: (streaming) => set({ streaming }),
|
||||||
|
@ -13,7 +13,9 @@ export type Message = {
|
|||||||
isBot: boolean
|
isBot: boolean
|
||||||
name: string
|
name: string
|
||||||
message: string
|
message: string
|
||||||
|
webSearch?: boolean
|
||||||
webSources: any[]
|
webSources: any[]
|
||||||
|
iodSearch?: boolean
|
||||||
iodSources: AllIodRegistryEntry
|
iodSources: AllIodRegistryEntry
|
||||||
images?: string[]
|
images?: string[]
|
||||||
search?: WebSearch
|
search?: WebSearch
|
||||||
@ -22,3 +24,5 @@ export type Message = {
|
|||||||
generationInfo?: any
|
generationInfo?: any
|
||||||
reasoning_time_taken?: number
|
reasoning_time_taken?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type Messages = Message[]
|
||||||
|
@ -13,6 +13,7 @@ import { PageAssitDatabase } from "@/db"
|
|||||||
|
|
||||||
import { enPOSTag, Segment, useDefault } from "segmentit"
|
import { enPOSTag, Segment, useDefault } from "segmentit"
|
||||||
import { getDefaultIodSources } from "@/libs/iod.ts"
|
import { getDefaultIodSources } from "@/libs/iod.ts"
|
||||||
|
import { IodDb } from "@/db/iod.ts"
|
||||||
|
|
||||||
const segment = useDefault(new Segment())
|
const segment = useDefault(new Segment())
|
||||||
export const tokenizeInput = function (input: string): string[] {
|
export const tokenizeInput = function (input: string): string[] {
|
||||||
@ -24,24 +25,9 @@ export const tokenizeInput = function (input: string): string[] {
|
|||||||
)
|
)
|
||||||
return words.filter((word) => word.w.length > 1).map((word) => word.w)
|
return words.filter((word) => word.w.length > 1).map((word) => word.w)
|
||||||
}
|
}
|
||||||
//doipUrl = tcp://reg01.public.internetofdata.cn:21037
|
|
||||||
export const _iodConfig = {
|
|
||||||
gatewayUrl: "tcp://reg01.public.internetofdata.cn:21037",
|
|
||||||
registry: "data/Registry",
|
|
||||||
localRepository: "data/Repository",
|
|
||||||
doBrowser: "http://021.node.internetapi.cn:21030/SCIDE/SCManager"
|
|
||||||
}
|
|
||||||
|
|
||||||
function getIodConfig() {
|
function getIodConfig() {
|
||||||
const val = localStorage.getItem("iod-connect")
|
return IodDb.getInstance().getIodConnection()
|
||||||
if (!val) {
|
|
||||||
return _iodConfig
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
return JSON.parse(val)
|
|
||||||
} catch {
|
|
||||||
return _iodConfig
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
export const iodConfigLocal = {
|
export const iodConfigLocal = {
|
||||||
gatewayUrl: "tcp://127.0.0.1:21036",
|
gatewayUrl: "tcp://127.0.0.1:21036",
|
||||||
@ -272,7 +258,7 @@ export const updateDialog = async function (
|
|||||||
})) ?? []
|
})) ?? []
|
||||||
|
|
||||||
updateBody.IoDSources =
|
updateBody.IoDSources =
|
||||||
Object.values( botMessage.iodSources as AllIodRegistryEntry).flatMap(iod => iod.data)?.map((r) => ({
|
Object.values((botMessage?.iodSources ?? {}) as AllIodRegistryEntry).flatMap(iod => iod.data)?.map((r) => ({
|
||||||
id: r.doId,
|
id: r.doId,
|
||||||
tokenCount:
|
tokenCount:
|
||||||
r.content || r.description
|
r.content || r.description
|
||||||
|
Loading…
x
Reference in New Issue
Block a user