improve reasoning toggle tests and refactor model capability checks

This commit is contained in:
2026-09-21 21:46:22 +02:00
parent 6cb0cbcee0
commit a8e348e0c7
8 changed files with 217 additions and 75 deletions
+24 -28
View File
@@ -18,7 +18,7 @@ import {
retryStylePrompts
} from "./chatMessageHelpers.js";
import {SearXNGSearchProvider, WebSearchError, buildWebSearchContext, buildWebSearchQuery, decideWebSearch, selectSearchResults, MAX_CANDIDATES} from "./webSearchService.js";
import {SearXNGSearchProvider, WebSearchError, buildWebSearchContext, retrieveWebSearch} from "./webSearchService.js";
import {supportsReasoning} from "../../public/app/modelCapabilities.js";
export function createChatService(repositories, modelService, config, webSearchProvider = new SearXNGSearchProvider(config)) {
@@ -267,12 +267,14 @@ export function createChatService(repositories, modelService, config, webSearchP
const personaStatePrompt = buildPersonaStatePrompt(repositories.getPersonaChatState(chatId, user));
if (personaStatePrompt) messagesPayload.push({role: "system", content: personaStatePrompt});
if (activePersona) messagesPayload.push({role: "system", content: buildRoleplayReplyGuardPrompt()});
if (webSearchContext) messagesPayload.push(webSearchContext[0]);
if (webSearchContext?.[1]) messagesPayload.push(webSearchContext[1]);
messagesPayload.push(...conversation.map((entry) => ({
const conversationMessages = conversation.map((entry) => ({
role: entry.role === "bot" ? "assistant" : "user",
content: entry.content
})));
}));
messagesPayload.push(...conversationMessages.slice(0, -1));
if (webSearchContext) messagesPayload.push(webSearchContext[0]);
if (webSearchContext?.[1]) messagesPayload.push(webSearchContext[1]);
if (conversationMessages.length) messagesPayload.push(conversationMessages.at(-1));
return {session: activeSession, activePersona, activeUserPersona, messagesPayload};
};
@@ -348,6 +350,7 @@ export function createChatService(repositories, modelService, config, webSearchP
const userMessageId = Number(inserted?.lastInsertRowid);
try {
let sources = null;
let searchState = "skipped";
let thinking = "";
const captureThinking = (chunk, fullThinking) => {
if (!useReasoning) return;
@@ -359,36 +362,29 @@ export function createChatService(repositories, modelService, config, webSearchP
activeSignal.throwIfAborted();
onStatus?.({status: "accepted"});
if (webSearch) {
const searchDecision = decideWebSearch(message);
let searchQuery = null;
let candidateCount = 0;
let selectedCount = 0;
if (searchDecision.needsSearch) {
onStatus?.({status: "searching"});
searchQuery = buildWebSearchQuery(message, searchDecision);
const candidates = await webSearchProvider.search(searchQuery, {
signal: activeSignal,
limit: MAX_CANDIDATES,
...(searchDecision.intent === "news" ? {category: "news"} : {})
});
candidateCount = candidates.length;
sources = selectSearchResults(message, candidates, searchDecision);
selectedCount = sources.length;
}
const search = await retrieveWebSearch(message, webSearchProvider, {
signal: activeSignal,
onSearching: () => onStatus?.({status: "searching"})
});
sources = search.sources;
searchState = search.state;
if (config.structuredRequestLoggingEnabled) {
console.log(JSON.stringify({
event: "web_search",
webSearchRequested: true,
searchNeeded: searchDecision.needsSearch,
query: searchQuery,
candidateCount,
selectedCount,
explicitSearchRequested: search.decision.explicitSearchIntent,
automaticSearchDecision: search.decision.automaticSearchDecision,
searchNeeded: search.decision.shouldSearch,
searchState,
queryCount: search.queries.length,
candidateCount: search.candidates.length,
selectedCount: sources?.length || 0,
webContextSupplied: sources !== null,
model: effectiveModel
}));
}
}
onStatus?.({status: "generating", ...(sources !== null ? {sourceCount: sources.length} : {})});
onStatus?.({status: "generating", searchState, ...(sources !== null ? {sourceCount: sources.length} : {})});
payload = buildConversationContext({user, chatId, session, message: null, sources});
return payload.activePersona
? generateValidatedRoleplayReply({
@@ -420,11 +416,11 @@ export function createChatService(repositories, modelService, config, webSearchP
repositories.completeChatTurn(chatId, userMessageId, fullReply, retryState, effectiveModel, sources, thinking);
repositories.touchChat(chatId, user);
scheduleContextSummaryUpdate({user, chatId, selectedModel: effectiveModel});
return {reply: fullReply, userMessageId, ...(sources ? {sources} : {})};
return {reply: fullReply, userMessageId, searchState, ...(sources ? {sources} : {})};
} catch (error) {
repositories.failChatTurn(chatId, userMessageId, String(error?.message || "Model request failed").slice(0, 500), webSearch ? userMessageId : effectiveParentId);
repositories.touchChat(chatId, user);
if (error instanceof WebSearchError) return {error: error.message, status: error.status};
if (error instanceof WebSearchError) return {error: error.message, status: error.status, searchState: "failed"};
throw error;
}
});