Compare commits

...

1 Commits
main ... chq

Author SHA1 Message Date
CaiHQ
e5cca132da naive search 2025-02-13 17:22:05 +08:00
17 changed files with 201 additions and 63 deletions

View File

@ -105,7 +105,8 @@
"rephrase": "言い換え",
"translate": "翻訳"
},
"citations": "引用",
"citations": "万维网引用",
"iodcitations":"数联网引用",
"downloadCode": "コードをダウンロード",
"date": {
"pinned": "固定",

View File

@ -105,7 +105,8 @@
"rephrase": "重述",
"translate": "翻译"
},
"citations": "引用",
"citations": "万维网引用",
"iodcitations":"数联网引用",
"downloadCode": "下载代码",
"date": {
"pinned": "已置顶",

View File

@ -1,6 +1,6 @@
{
"newChat": "新聊天",
"selectAPrompt": "选择一个提示词",
"selectAPrompt": "本地回答",
"githubRepository": "GitHub 仓库",
"settings": "设置",
"sidebarTitle": "聊天历史",

View File

@ -37,6 +37,7 @@ type Props = {
webSearch?: {}
isSearchingInternet?: boolean
sources?: any[]
iodSources?:any[]
hideEditAndRegenerate?: boolean
onSourceClick?: (source: any) => void
isTTSEnabled?: boolean
@ -48,7 +49,6 @@ type Props = {
export const PlaygroundMessage = (props: Props) => {
const [isBtnPressed, setIsBtnPressed] = React.useState(false)
const [editMode, setEditMode] = React.useState(false)
const { t } = useTranslation("common")
const { cancel, isSpeaking, speak } = useTTS()
return (
@ -166,6 +166,34 @@ export const PlaygroundMessage = (props: Props) => {
</div>
)}
{props.isBot && props?.iodSources && props?.iodSources.length > 0 && (
<Collapse
className="mt-6"
ghost
items={[
{
key: "1",
label: (
<div className="italic text-gray-500 dark:text-gray-400">
{t("iodcitations")}
</div>
),
children: (
<div className="block">
{props?.iodSources?.map((source, index) => (
<MessageSource
onSourceClick={props.onSourceClick}
key={index}
source={source}
index = {index}
/>
))}
</div>
)
}
]}
/>
)}
{props.isBot && props?.sources && props?.sources.length > 0 && (
<Collapse
className="mt-6"
@ -179,12 +207,13 @@ export const PlaygroundMessage = (props: Props) => {
</div>
),
children: (
<div className="mb-3 flex flex-wrap gap-2">
<div className="block">
{props?.sources?.map((source, index) => (
<MessageSource
onSourceClick={props.onSourceClick}
key={index}
source={source}
index = {index}
/>
))}
</div>

View File

@ -9,29 +9,42 @@ type Props = {
pageContent?: string
content?: string
}
key: number
onSourceClick?: (source: any) => void
index: number
}
export const MessageSource: React.FC<Props> = ({ source, onSourceClick }) => {
export const MessageSource: React.FC<Props> = ({ source, key, onSourceClick, index}) => {
if (source?.mode === "rag" || source?.mode === "chat") {
return (
<button
onClick={() => {
onSourceClick && onSourceClick(source)
}}
className="inline-flex gap-2 cursor-pointer transition-shadow duration-300 ease-in-out hover:shadow-lg items-center rounded-md bg-gray-100 p-1 text-xs text-gray-800 border border-gray-300 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-100 opacity-80 hover:opacity-100">
<KnowledgeIcon type={source.type} className="h-3 w-3" />
<div className="block items-center gap-1 text-xs text-gray-800 dark:text-gray-100 mb-1">
<span className="text-xs font-medium">[{index + 1}]</span> {/* 显示序号 */}
<span className="text-xs">{source.name}</span>
</button>
)
}
return (
<a
href={source?.url}
target="_blank"
className="inline-flex cursor-pointer transition-shadow duration-300 ease-in-out hover:shadow-lg items-center rounded-md bg-gray-100 p-1 text-xs text-gray-800 border border-gray-300 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-100 opacity-80 hover:opacity-100">
<span className="text-xs">{source.name}</span>
className="text-xs text-blue-500 hover:underline"
onClick={(e) => {
e.preventDefault(); // 阻止默认的链接行为
onSourceClick && onSourceClick(source); // 调用自定义点击事件
}}
>
{source.url}
</a>
</div>
);
}
return (
<div className="block items-center gap-1 text-xs text-gray-800 dark:text-gray-100 mb-1">
<span className="text-xs font-medium">[{index + 1}]</span> {/* 显示序号 */}
<a
href={source?.url}
target="_blank"
className="text-xs text-blue-500 hover:underline"
>
{source.name}
</a>
</div>
)
}

View File

@ -37,6 +37,7 @@ export const PlaygroundChat = () => {
isProcessing={streaming}
isSearchingInternet={isSearchingInternet}
sources={message.sources}
iodSources={message.iodSources}
onEditFormSubmit={(value, isSend) => {
editMessage(index, value, !message.isBot, isSend)
}}

View File

@ -126,6 +126,7 @@ export const PlaygroundForm = ({ dropedFile }: Props) => {
}
}, [transcript])
/*
React.useEffect(() => {
if (selectedQuickPrompt) {
const word = getVariable(selectedQuickPrompt)
@ -142,7 +143,7 @@ export const PlaygroundForm = ({ dropedFile }: Props) => {
}
}
}, [selectedQuickPrompt])
*/
const queryClient = useQueryClient()
const { mutateAsync: sendMessage } = useMutation({
@ -299,23 +300,6 @@ export const PlaygroundForm = ({ dropedFile }: Props) => {
{...form.getInputProps("message")}
/>
<div className="mt-2 flex justify-between items-center">
<div className="flex">
{!selectedKnowledge && (
<Tooltip title={t("tooltip.searchInternet")}>
<div className="inline-flex items-center gap-2">
<PiGlobe
className={`h-5 w-5 dark:text-gray-300 `}
/>
<Switch
value={webSearch}
onChange={(e) => setWebSearch(e)}
checkedChildren={t("form.webSearch.on")}
unCheckedChildren={t("form.webSearch.off")}
/>
</div>
</Tooltip>
)}
</div>
<div className="flex !justify-end gap-3">
{!selectedKnowledge && (
<Tooltip title={t("tooltip.uploadImage")}>

View File

@ -0,0 +1,13 @@
<Tooltip title={t("tooltip.searchInternet")}>
<div className="inline-flex items-center gap-2">
<PiGlobe
className={`h-5 w-5 dark:text-gray-300 `}
/>
<Switch
value={webSearch}
onChange={(e) => setWebSearch(e)}
checkedChildren={t("form.webSearch.on")}
unCheckedChildren={t("form.webSearch.off")}
/>
</div>
</Tooltip>

View File

@ -32,6 +32,7 @@ type Props = {
setHistoryId: (historyId: string) => void
setSelectedModel: (model: string) => void
setSelectedSystemPrompt: (prompt: string) => void
setSelectedQuickPrompt: (prompt: string | undefined) => void
setSystemPrompt: (prompt: string) => void
clearChat: () => void
temporaryChat: boolean
@ -46,6 +47,7 @@ export const Sidebar = ({
setHistoryId,
setSelectedModel,
setSelectedSystemPrompt,
setSelectedQuickPrompt,
clearChat,
historyId,
setSystemPrompt,

View File

@ -40,6 +40,7 @@ export const SidePanelBody = () => {
isProcessing={streaming}
isSearchingInternet={isSearchingInternet}
sources={message.sources}
iodSources={message.iodSources}
onEditFormSubmit={(value) => {
editMessage(index, value, !message.isBot)
}}

View File

@ -30,6 +30,7 @@ type Message = {
content: string
images?: string[]
sources?: string[]
iodSources?:string[]
search?: WebSearch
createdAt: number
reasoning_time_taken?: number
@ -238,7 +239,7 @@ export const generateID = () => {
export const saveHistory = async (
title: string,
is_rag?: boolean,
message_source?: "copilot" | "web-ui"
message_source?: "copilot" | "web-ui",
) => {
const id = generateID()
const createdAt = Date.now()
@ -255,6 +256,7 @@ export const saveMessage = async (
content: string,
images: string[],
source?: any[],
iodSource?:any[],
time?: number,
message_type?: string,
generationInfo?: any,
@ -274,6 +276,7 @@ export const saveMessage = async (
images,
createdAt,
sources: source,
iodSources:iodSource,
messageType: message_type,
generationInfo: generationInfo,
reasoning_time_taken
@ -304,6 +307,7 @@ export const formatToMessage = (messages: MessageHistory): MessageType[] => {
message: message.content,
name: message.name,
sources: message?.sources || [],
iodSources: message?.iodSources || [],
images: message.images || [],
generationInfo: message?.generationInfo,
reasoning_time_taken: message?.reasoning_time_taken

View File

@ -62,6 +62,7 @@ export const saveMessageOnError = async ({
userMessage,
[image],
[],
[],
1,
message_type
)
@ -73,6 +74,7 @@ export const saveMessageOnError = async ({
botMessage,
[],
[],
[],
2,
message_type
)
@ -91,6 +93,7 @@ export const saveMessageOnError = async ({
userMessage,
[image],
[],
[],
1,
message_type
)
@ -102,6 +105,7 @@ export const saveMessageOnError = async ({
botMessage,
[],
[],
[],
2,
message_type
)
@ -127,6 +131,7 @@ export const saveMessageOnSuccess = async ({
image,
fullText,
source,
iodSource,
message_source = "web-ui",
message_type, generationInfo,
prompt_id,
@ -141,6 +146,7 @@ export const saveMessageOnSuccess = async ({
image: string
fullText: string
source: any[]
iodSource: any[]
message_source?: "copilot" | "web-ui",
message_type?: string
generationInfo?: any
@ -157,6 +163,7 @@ export const saveMessageOnSuccess = async ({
message,
[image],
[],
[],
1,
message_type,
generationInfo,
@ -170,6 +177,7 @@ export const saveMessageOnSuccess = async ({
fullText,
[],
source,
iodSource,
2,
message_type,
generationInfo,
@ -189,6 +197,7 @@ export const saveMessageOnSuccess = async ({
message,
[image],
[],
[],
1,
message_type,
generationInfo,
@ -201,6 +210,7 @@ export const saveMessageOnSuccess = async ({
fullText,
[],
source,
iodSource,
2,
message_type,
generationInfo,

View File

@ -186,6 +186,7 @@ export const useMessage = () => {
name: "You",
message,
sources: [],
iodSources:[],
images: []
},
{
@ -193,6 +194,7 @@ export const useMessage = () => {
name: selectedModel,
message: "▋",
sources: [],
iodSources:[],
id: generateMessageId
}
]
@ -204,6 +206,7 @@ export const useMessage = () => {
name: selectedModel,
message: "▋",
sources: [],
iodSources:[],
id: generateMessageId
}
]
@ -497,7 +500,7 @@ export const useMessage = () => {
content: fullText
}
])
const iodSource = []
await saveMessageOnSuccess({
historyId,
setHistoryId,
@ -507,6 +510,7 @@ export const useMessage = () => {
image,
fullText,
source,
iodSource,
message_source: "copilot",
generationInfo,
reasoning_time_taken: timetaken
@ -607,6 +611,7 @@ export const useMessage = () => {
name: "You",
message,
sources: [],
iodSources:[],
images: []
},
{
@ -614,6 +619,7 @@ export const useMessage = () => {
name: selectedModel,
message: "▋",
sources: [],
iodSources: [],
id: generateMessageId
}
]
@ -625,6 +631,7 @@ export const useMessage = () => {
name: selectedModel,
message: "▋",
sources: [],
iodSources: [],
id: generateMessageId
}
]
@ -788,6 +795,7 @@ export const useMessage = () => {
image,
fullText,
source: [],
iodSource:[],
message_source: "copilot",
generationInfo,
reasoning_time_taken: timetaken
@ -892,6 +900,7 @@ export const useMessage = () => {
name: "You",
message,
sources: [],
iodSources: [],
images: [image]
},
{
@ -899,6 +908,7 @@ export const useMessage = () => {
name: selectedModel,
message: "▋",
sources: [],
iodSources: [],
id: generateMessageId
}
]
@ -910,6 +920,7 @@ export const useMessage = () => {
name: selectedModel,
message: "▋",
sources: [],
iodSources: [],
id: generateMessageId
}
]
@ -1078,6 +1089,7 @@ export const useMessage = () => {
image,
fullText,
source: [],
iodSource:[],
message_source: "copilot",
generationInfo,
reasoning_time_taken: timetaken
@ -1177,6 +1189,7 @@ export const useMessage = () => {
name: "You",
message,
sources: [],
iodSources: [],
images: [image]
},
{
@ -1184,6 +1197,7 @@ export const useMessage = () => {
name: selectedModel,
message: "▋",
sources: [],
iodSources: [],
id: generateMessageId
}
]
@ -1195,6 +1209,7 @@ export const useMessage = () => {
name: selectedModel,
message: "▋",
sources: [],
iodSources: [],
id: generateMessageId
}
]
@ -1271,9 +1286,10 @@ export const useMessage = () => {
query = removeReasoning(query)
}
const { prompt, source } = await getSystemPromptForWeb(query)
const { prompt, source, iodSource } = await getSystemPromptForWeb(query, selectedQuickPrompt)
setIsSearchingInternet(false)
console.log("iodSource:")
console.log(iodSource)
// message = message.trim().replaceAll("\n", " ")
let humanMessage = await humanMessageFormatter({
@ -1395,6 +1411,7 @@ export const useMessage = () => {
...message,
message: fullText,
sources: source,
iodSources: iodSource,
generationInfo,
reasoning_time_taken: timetaken
}
@ -1425,6 +1442,7 @@ export const useMessage = () => {
image,
fullText,
source,
iodSource,
generationInfo,
reasoning_time_taken: timetaken
})
@ -1524,6 +1542,7 @@ export const useMessage = () => {
name: "You",
message,
sources: [],
iodSources: [],
images: [image],
messageType: messageType
},
@ -1532,6 +1551,7 @@ export const useMessage = () => {
name: selectedModel,
message: "▋",
sources: [],
iodSources: [],
id: generateMessageId
}
]
@ -1543,6 +1563,7 @@ export const useMessage = () => {
name: selectedModel,
message: "▋",
sources: [],
iodSources: [],
id: generateMessageId
}
]
@ -1689,6 +1710,7 @@ export const useMessage = () => {
image,
fullText,
source: [],
iodSource:[],
message_source: "copilot",
message_type: messageType,
generationInfo,

View File

@ -173,6 +173,7 @@ export const useMessageOption = () => {
name: "You",
message,
sources: [],
iodSources: [],
images: [image]
},
{
@ -180,6 +181,7 @@ export const useMessageOption = () => {
name: selectedModel,
message: "▋",
sources: [],
iodSources: [],
id: generateMessageId
}
]
@ -191,6 +193,7 @@ export const useMessageOption = () => {
name: selectedModel,
message: "▋",
sources: [],
iodSources: [],
id: generateMessageId
}
]
@ -204,7 +207,7 @@ export const useMessageOption = () => {
setIsSearchingInternet(true)
let query = message
/*
if (newMessage.length > 2) {
let questionPrompt = await geWebSearchFollowUpPrompt()
const lastTenMessages = newMessage.slice(-10)
@ -267,10 +270,17 @@ export const useMessageOption = () => {
query = response.content.toString()
query = removeReasoning(query)
}
const { prompt, source } = await getSystemPromptForWeb(query)
*/
const quickPrompt = selectedQuickPrompt;
console.log("quick prompt:"+quickPrompt)
const { prompt, source, iodSource } = await getSystemPromptForWeb(query, quickPrompt)
setIsSearchingInternet(false)
console.log("iodSource from useMessageOption:")
console.log(iodSource)
console.log("prompt")
console.log(prompt)
console.log("query")
console.log(query)
// message = message.trim().replaceAll("\n", " ")
let humanMessage = await humanMessageFormatter({
@ -391,6 +401,7 @@ export const useMessageOption = () => {
...message,
message: fullText,
sources: source,
iodSources:iodSource,
generationInfo,
reasoning_time_taken: timetaken
}
@ -421,6 +432,7 @@ export const useMessageOption = () => {
image,
fullText,
source,
iodSource,
generationInfo,
reasoning_time_taken: timetaken
})
@ -553,6 +565,7 @@ export const useMessageOption = () => {
name: "You",
message,
sources: [],
iodSources: [],
images: [image]
},
{
@ -560,6 +573,7 @@ export const useMessageOption = () => {
name: selectedModel,
message: "▋",
sources: [],
iodSources: [],
id: generateMessageId
}
]
@ -571,6 +585,7 @@ export const useMessageOption = () => {
name: selectedModel,
message: "▋",
sources: [],
iodSources: [],
id: generateMessageId
}
]
@ -757,6 +772,7 @@ export const useMessageOption = () => {
image,
fullText,
source: [],
iodSource:[],
generationInfo,
prompt_content: promptContent,
prompt_id: promptId,
@ -856,6 +872,7 @@ export const useMessageOption = () => {
name: "You",
message,
sources: [],
iodSources: [],
images: []
},
{
@ -863,6 +880,7 @@ export const useMessageOption = () => {
name: selectedModel,
message: "▋",
sources: [],
iodSources: [],
id: generateMessageId
}
]
@ -874,6 +892,7 @@ export const useMessageOption = () => {
name: selectedModel,
message: "▋",
sources: [],
iodSources: [],
id: generateMessageId
}
]
@ -979,7 +998,8 @@ export const useMessageOption = () => {
}
})
// message = message.trim().replaceAll("\n", " ")
const iodSource = []
//TODO not support iodSource in RAG
let humanMessage = await humanMessageFormatter({
content: [
{
@ -1077,6 +1097,7 @@ export const useMessageOption = () => {
...message,
message: fullText,
sources: source,
iodSources: iodSource,
generationInfo,
reasoning_time_taken: timetaken
}
@ -1107,6 +1128,7 @@ export const useMessageOption = () => {
image,
fullText,
source,
iodSource,
generationInfo,
reasoning_time_taken: timetaken
})

View File

@ -15,6 +15,7 @@ export type Message = {
name: string
message: string
sources: any[]
iodSources: any[]
images?: string[]
search?: WebSearch
reasoning_time_taken?: number

View File

@ -12,6 +12,7 @@ export type Message = {
name: string
message: string
sources: any[]
iodSources: any[]
images?: string[]
search?: WebSearch
messageType?: string

View File

@ -8,6 +8,7 @@ import { getWebsiteFromQuery, processSingleWebsite } from "./website"
import { searxngSearch } from "./search-engines/searxng"
import { braveAPISearch } from "./search-engines/brave-api"
import { webBaiduSearch } from "./search-engines/baidu"
import { LucideToggleRight } from "lucide-react"
const getHostName = (url: string) => {
try {
@ -37,8 +38,29 @@ const searchWeb = (provider: string, query: string) => {
}
}
export const getSystemPromptForWeb = async (query: string) => {
export const getSystemPromptForWeb = async (query: string, promptMode) => {
try {
if (!promptMode){
return {
prompt: "",
source: [],
iodSource:[]
}
}
let iodsearch = []
if (promptMode.indexOf("iod_search_results")!=-1){
iodsearch = [
{
url:"http://bdware.cn/resolve?id=CSTR:432421111.1233.53323",
content:"数联网Internet Of Data):数据作为互联网上可独立管理的资源,在“物理/机器”互联网之上形成一个“虚拟/数据”网络,实现全网一体化的数据互联互通互操作。",
id:"CSTR:432421111.1233.53323,数联网定义"
}, {
url:"http://bdware.cn/resolve?id=CSTR:1121311.3423.7754",
content:"数据空间:面向具体的领域和业务场景,按照数据所对应的物理实体的结构、关系来对数据进行管理和组织,构成物理世界的数字孪生。",
id:"CSTR:1121311.3423.7754,数据空间定义"
}
]
}
const websiteVisit = getWebsiteFromQuery(query)
let search: {
@ -47,34 +69,37 @@ export const getSystemPromptForWeb = async (query: string) => {
}[] = []
const isVisitSpecificWebsite = await getIsVisitSpecificWebsite()
if (isVisitSpecificWebsite && websiteVisit.hasUrl) {
const url = websiteVisit.url
const queryWithoutUrl = websiteVisit.queryWithouUrls
search = await processSingleWebsite(url, queryWithoutUrl)
} else {
} else if (promptMode.indexOf("web_search_results")!=-1) {
const searchProvider = await getSearchProvider()
search = await searchWeb(searchProvider, query)
}
const search_results = search
.map(
(result, idx) =>
`<result source="${result.url}" id="${idx}">${result.content}</result>`
`<result source="${result.url}" id="${idx+1}">${result.content}</result>`
)
.join("\n")
const current_date_time = new Date().toLocaleString()
const system = await getWebSearchPrompt()
const system = promptMode
const iod_search_results= iodsearch.map(
(result, idx) =>
`<result source="${result.url}" id="${idx+1}">${result.content}</result>`
)
.join("\n")
console.log("iod_search_xml in web.ts")
console.log(iod_search_results)
const prompt = system
.replace("{current_date_time}", current_date_time)
.replace("{search_results}", search_results)
.replace("{web_search_results}", search_results)
.replace("{iod_search_results}",iod_search_results)
return {
prompt,
source: search.map((result) => {
@ -83,13 +108,21 @@ export const getSystemPromptForWeb = async (query: string) => {
name: getHostName(result.url),
type: "url"
}
}),
iodSource: iodsearch.map((result) => {
return {
url: result.url,
name: result.id,
type: "url"
}
})
}
} catch (e) {
console.error(e)
return {
prompt: "",
source: []
source: [],
iodSource:[]
}
}
}