feat: add web search tool with reranking support
Integrates SearXNG web search as a tool available during chat when the agent has search enabled. Supports optional reranking of results via a configurable reranking model. Replaces Python subprocess evaluation with @pydantic/monty WASM runtime. Introduces stable tool call ID mapping to avoid exposing provider-native IDs to the database.
This commit is contained in:
@@ -123,9 +123,9 @@ export const useAgents = async () => {
|
||||
a.id === id ? agent : a
|
||||
);
|
||||
},
|
||||
async onResponse() {
|
||||
await refresh();
|
||||
}
|
||||
// async onResponse() {
|
||||
// await refresh();
|
||||
// }
|
||||
});
|
||||
}
|
||||
|
||||
@@ -166,7 +166,7 @@ export const useAgents = async () => {
|
||||
body: topic,
|
||||
onRequest() {
|
||||
agents.value = agents.value.map(a =>
|
||||
a.id === agentId ? { ...a, topics: [{ ...topic, createdAt: new Date() }, ...a.topics] } : a
|
||||
a.id === agentId ? { ...a, topics: [{ ...topic, createdAt: new Date() }, ...a.topics] } as AgentWithTopics : a
|
||||
);
|
||||
},
|
||||
onResponseError() {
|
||||
|
||||
+30
-22
@@ -52,7 +52,6 @@ export const useChat = async (topicId: MaybeRef<string>, connect = true) => {
|
||||
if (!msg) continue;
|
||||
|
||||
for (const [partId, content] of parts) {
|
||||
console.log("content", content);
|
||||
const part = msg.parts?.find(p => p.id === partId);
|
||||
if (part) {
|
||||
part.content += content;
|
||||
@@ -135,7 +134,6 @@ export const useChat = async (topicId: MaybeRef<string>, connect = true) => {
|
||||
const messageBuffer = textDeltaBuffer.get(payload.messageId)!;
|
||||
const existing = messageBuffer.get(payload.partId) || '';
|
||||
messageBuffer.set(payload.partId, existing + payload.content);
|
||||
console.log("messageBuffer", messageBuffer, existing + payload.content);
|
||||
|
||||
scheduleFlush();
|
||||
break;
|
||||
@@ -303,8 +301,6 @@ export const useChat = async (topicId: MaybeRef<string>, connect = true) => {
|
||||
baseMessage: BaseMessage,
|
||||
onRequest?: () => void,
|
||||
): Promise<Result<void, ChatErrorType>> => {
|
||||
console.log("sendMessage", baseMessage);
|
||||
|
||||
const { user } = useAuth();
|
||||
if (!user.value) return Err(ChatErrorType.NoUser);
|
||||
|
||||
@@ -316,8 +312,6 @@ export const useChat = async (topicId: MaybeRef<string>, connect = true) => {
|
||||
fileIds: baseMessage.fileIds,
|
||||
}
|
||||
|
||||
console.log("sendMessage", message, baseMessage.content, baseMessage.fileIds);
|
||||
|
||||
await $fetch(`/api/topic/${unref(topicId)}/message`, {
|
||||
method: 'POST',
|
||||
body: {
|
||||
@@ -355,19 +349,46 @@ export const useChat = async (topicId: MaybeRef<string>, connect = true) => {
|
||||
}
|
||||
};
|
||||
|
||||
const startGeneration = async (model: ModelWithProvider) => {
|
||||
console.log(model.provider);
|
||||
const startGeneration = async (model: ModelWithProvider, parentMessageId?: string, agentIdOverride?: string) => {
|
||||
const providerApiKeyRes = await getProviderAPIKey(model.provider);
|
||||
if (providerApiKeyRes.ok === false) {
|
||||
return providerApiKeyRes;
|
||||
}
|
||||
const providerApiKey = providerApiKeyRes.data;
|
||||
|
||||
const { agents } = await useAgents();
|
||||
|
||||
const agent = agents.value.find(agent => agent.id === (agentIdOverride || topic.value?.agentId));
|
||||
if (!agent) {
|
||||
return Err(ChatErrorType.NoAgent);
|
||||
}
|
||||
|
||||
const { settings } = await useUserSettings();
|
||||
|
||||
let rerank = undefined;
|
||||
|
||||
if (agent.config?.search?.rerank && settings.value.systemAssistants.rerank.enabled) {
|
||||
const rerankModel = await useModels().then(m => m.allModels.value.find(m => m.id === settings.value.systemAssistants.rerank.modelId));
|
||||
if (rerankModel) {
|
||||
const rerankProviderApiKeyRes = await getProviderAPIKey(rerankModel.provider);
|
||||
if (rerankProviderApiKeyRes.ok === false) {
|
||||
return rerankProviderApiKeyRes;
|
||||
}
|
||||
const rerankProviderApiKey = rerankProviderApiKeyRes.data;
|
||||
rerank = {
|
||||
modelId: rerankModel.id,
|
||||
providerApiKey: rerankProviderApiKey,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
await $fetch(`/api/topic/${unref(topicId)}/chat`, {
|
||||
method: 'POST',
|
||||
body: {
|
||||
modelId: model.id,
|
||||
providerApiKey,
|
||||
rerank,
|
||||
parentMessageId,
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -399,12 +420,6 @@ export const useChat = async (topicId: MaybeRef<string>, connect = true) => {
|
||||
}
|
||||
let targetMessageIndex = topicMessages.indexOf(targetMessage);
|
||||
|
||||
const providerApiKeyRes = await getProviderAPIKey(model.provider);
|
||||
if (providerApiKeyRes.ok === false) {
|
||||
return providerApiKeyRes;
|
||||
}
|
||||
const providerApiKey = providerApiKeyRes.data;
|
||||
|
||||
let parentMessageId = undefined;
|
||||
let focusedMessages: MessageEntity[] | undefined;
|
||||
if (targetMessage.role === 'user') {
|
||||
@@ -429,14 +444,7 @@ export const useChat = async (topicId: MaybeRef<string>, connect = true) => {
|
||||
focusedMessages = topicMessages;
|
||||
}
|
||||
|
||||
await $fetch(`/api/topic/${unref(topicId)}/chat`, {
|
||||
method: 'POST',
|
||||
body: {
|
||||
modelId: model.id,
|
||||
providerApiKey,
|
||||
parentMessageId,
|
||||
},
|
||||
});
|
||||
startGeneration(model, parentMessageId);
|
||||
|
||||
return Ok(undefined);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ export type Provider = typeof schema.providers.$inferSelect;
|
||||
|
||||
export type ProviderWithModels = Provider & {
|
||||
models: Model[];
|
||||
defaultBaseUrl?: string;
|
||||
};
|
||||
|
||||
export type ModelWithProvider = Model & {
|
||||
|
||||
Reference in New Issue
Block a user