Remove clinical assistant source lock
All checks were successful
Forgejo Android APK / Build signed APK (push) Successful in 1m54s
All checks were successful
Forgejo Android APK / Build signed APK (push) Successful in 1m54s
This commit is contained in:
parent
018913a845
commit
604f6abb49
4 changed files with 4 additions and 36 deletions
|
|
@ -8,7 +8,6 @@ services:
|
||||||
- .env
|
- .env
|
||||||
environment:
|
environment:
|
||||||
CLINICAL_ASSISTANT_MCP_URL: http://mcp:8000/mcp
|
CLINICAL_ASSISTANT_MCP_URL: http://mcp:8000/mcp
|
||||||
CLINICAL_ASSISTANT_SOURCE_FILE_PATH: Medical Library/Pediatrics/Kliegman%20R.%20Nelson%20Textbook%20of%20Pediatrics%20%202-Volume%20Set%2022ed%202024.pdf
|
|
||||||
REDIS_URL: redis://ped-ai-redis:6379
|
REDIS_URL: redis://ped-ai-redis:6379
|
||||||
LOKI_URL: http://monitoring-loki:3100
|
LOKI_URL: http://monitoring-loki:3100
|
||||||
LITELLM_API_BASE: http://litellm:4000
|
LITELLM_API_BASE: http://litellm:4000
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,6 @@ var {
|
||||||
var {
|
var {
|
||||||
normalizeMcpSearchResponse,
|
normalizeMcpSearchResponse,
|
||||||
normalizeMcpMultimodalResponse,
|
normalizeMcpMultimodalResponse,
|
||||||
filterSourcesByFilePath,
|
|
||||||
dedupeSources,
|
dedupeSources,
|
||||||
isVisualSourceQuery,
|
isVisualSourceQuery,
|
||||||
buildMultimodalSearchQuery,
|
buildMultimodalSearchQuery,
|
||||||
|
|
@ -49,7 +48,6 @@ var MAX_SAVED_CHATS_PER_USER = 100;
|
||||||
var MAX_SAVED_CHAT_PAYLOAD = 250000;
|
var MAX_SAVED_CHAT_PAYLOAD = 250000;
|
||||||
var MAX_SAVED_CHAT_TITLE = 160;
|
var MAX_SAVED_CHAT_TITLE = 160;
|
||||||
var IMAGE_JOB_TTL_SECONDS = 15 * 60;
|
var IMAGE_JOB_TTL_SECONDS = 15 * 60;
|
||||||
var SOURCE_LOCK_SEARCH_LIMIT = 50;
|
|
||||||
var imageJobs = new Map();
|
var imageJobs = new Map();
|
||||||
var promptPool = createClinicalPromptPool({
|
var promptPool = createClinicalPromptPool({
|
||||||
redisCache: redisCache,
|
redisCache: redisCache,
|
||||||
|
|
@ -377,7 +375,6 @@ async function prepareAssistantChat(body) {
|
||||||
var contextChars = clampInt(await getSetting('clinical_assistant.context_chars', '1400'), 300, 4000, 1400);
|
var contextChars = clampInt(await getSetting('clinical_assistant.context_chars', '1400'), 300, 4000, 1400);
|
||||||
var behavior = await getSetting('clinical_assistant.system_behavior', DEFAULT_BEHAVIOR) || DEFAULT_BEHAVIOR;
|
var behavior = await getSetting('clinical_assistant.system_behavior', DEFAULT_BEHAVIOR) || DEFAULT_BEHAVIOR;
|
||||||
var includeContext = body.includeContext !== false;
|
var includeContext = body.includeContext !== false;
|
||||||
var sourceFilePath = String(process.env.CLINICAL_ASSISTANT_SOURCE_FILE_PATH || '').trim();
|
|
||||||
|
|
||||||
if (GREETING_RE.test(message)) {
|
if (GREETING_RE.test(message)) {
|
||||||
return { direct: {
|
return { direct: {
|
||||||
|
|
@ -396,8 +393,7 @@ async function prepareAssistantChat(body) {
|
||||||
return message;
|
return message;
|
||||||
});
|
});
|
||||||
var searchResponse = await semanticSearch(searchQuery, {
|
var searchResponse = await semanticSearch(searchQuery, {
|
||||||
// MCP has no source-path filter. Retrieve a larger candidate set, then enforce the lock locally.
|
limit: searchLimit,
|
||||||
limit: sourceFilePath ? SOURCE_LOCK_SEARCH_LIMIT : searchLimit,
|
|
||||||
includeContext: includeContext,
|
includeContext: includeContext,
|
||||||
contextChars: contextChars
|
contextChars: contextChars
|
||||||
});
|
});
|
||||||
|
|
@ -406,10 +402,10 @@ async function prepareAssistantChat(body) {
|
||||||
console.warn('[clinical-assistant] multimodal search skipped:', e.message);
|
console.warn('[clinical-assistant] multimodal search skipped:', e.message);
|
||||||
return null;
|
return null;
|
||||||
}) : null;
|
}) : null;
|
||||||
var rawTextResults = filterSourcesByFilePath(normalizeMcpSearchResponse(searchResponse), sourceFilePath);
|
var rawTextResults = normalizeMcpSearchResponse(searchResponse);
|
||||||
var rawMultimodalResults = await classifyAndRerankMultimodalResults(
|
var rawMultimodalResults = await classifyAndRerankMultimodalResults(
|
||||||
message + ' ' + searchQuery,
|
message + ' ' + searchQuery,
|
||||||
filterSourcesByFilePath(normalizeMcpMultimodalResponse(multimodalResponse), sourceFilePath)
|
normalizeMcpMultimodalResponse(multimodalResponse)
|
||||||
);
|
);
|
||||||
var rawResults = rawTextResults.concat(rawMultimodalResults);
|
var rawResults = rawTextResults.concat(rawMultimodalResults);
|
||||||
console.info('[clinical-assistant] retrieval counts:', {
|
console.info('[clinical-assistant] retrieval counts:', {
|
||||||
|
|
@ -450,8 +446,7 @@ async function prepareAssistantChat(body) {
|
||||||
query: searchQuery,
|
query: searchQuery,
|
||||||
rewritten: searchQuery !== message,
|
rewritten: searchQuery !== message,
|
||||||
verifiedChunkCount: searchResponse.verified_chunk_count || searchResponse.verifiedChunkCount || 0,
|
verifiedChunkCount: searchResponse.verified_chunk_count || searchResponse.verifiedChunkCount || 0,
|
||||||
droppedDocumentCount: searchResponse.dropped_document_count || searchResponse.droppedDocumentCount || 0,
|
droppedDocumentCount: searchResponse.dropped_document_count || searchResponse.droppedDocumentCount || 0
|
||||||
sourceLocked: Boolean(sourceFilePath)
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -89,18 +89,6 @@ function normalizeMcpMultimodalResponse(result) {
|
||||||
}).filter(function(r) { return r.page; });
|
}).filter(function(r) { return r.page; });
|
||||||
}
|
}
|
||||||
|
|
||||||
function filterSourcesByFilePath(results, filePath) {
|
|
||||||
if (!filePath) return results;
|
|
||||||
var wanted = normalizeFilePath(filePath);
|
|
||||||
return results.filter(function(result) {
|
|
||||||
return normalizeFilePath(result && result.file_path) === wanted;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function normalizeFilePath(filePath) {
|
|
||||||
try { return decodeURIComponent(String(filePath || '')).replace(/^\/+/, ''); } catch (e) { return String(filePath || '').replace(/^\/+/, ''); }
|
|
||||||
}
|
|
||||||
|
|
||||||
function dedupeSources(results) {
|
function dedupeSources(results) {
|
||||||
var seen = new Map();
|
var seen = new Map();
|
||||||
var out = [];
|
var out = [];
|
||||||
|
|
@ -283,7 +271,6 @@ function cleanSourceExcerpt(text) {
|
||||||
module.exports = {
|
module.exports = {
|
||||||
normalizeMcpSearchResponse: normalizeMcpSearchResponse,
|
normalizeMcpSearchResponse: normalizeMcpSearchResponse,
|
||||||
normalizeMcpMultimodalResponse: normalizeMcpMultimodalResponse,
|
normalizeMcpMultimodalResponse: normalizeMcpMultimodalResponse,
|
||||||
filterSourcesByFilePath: filterSourcesByFilePath,
|
|
||||||
dedupeSources: dedupeSources,
|
dedupeSources: dedupeSources,
|
||||||
isVisualSourceQuery: isVisualSourceQuery,
|
isVisualSourceQuery: isVisualSourceQuery,
|
||||||
buildMultimodalSearchQuery: buildMultimodalSearchQuery,
|
buildMultimodalSearchQuery: buildMultimodalSearchQuery,
|
||||||
|
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
const test = require('node:test');
|
|
||||||
const assert = require('node:assert/strict');
|
|
||||||
|
|
||||||
const { filterSourcesByFilePath } = require('../src/utils/clinicalRetrieval');
|
|
||||||
|
|
||||||
test('source lock keeps only the selected book regardless of URL encoding', () => {
|
|
||||||
const path = 'Medical Library/Pediatrics/Kliegman R. Nelson Textbook of Pediatrics 2-Volume Set 22ed 2024.pdf';
|
|
||||||
const sources = [
|
|
||||||
{ title: 'Nelson', file_path: 'Medical Library/Pediatrics/Kliegman%20R.%20Nelson%20Textbook%20of%20Pediatrics%20%202-Volume%20Set%2022ed%202024.pdf' },
|
|
||||||
{ title: 'Other book', file_path: 'Medical Library/Pediatrics/Other.pdf' }
|
|
||||||
];
|
|
||||||
assert.deepEqual(filterSourcesByFilePath(sources, path), [sources[0]]);
|
|
||||||
});
|
|
||||||
Loading…
Reference in a new issue