Add logging for embedding config loading and fix KB search dedup
All checks were successful
BotServer CI/CD / build (push) Successful in 4m14s
All checks were successful
BotServer CI/CD / build (push) Successful in 4m14s
This commit is contained in:
parent
148ad0cc7c
commit
cbf8e024d3
3 changed files with 71 additions and 58 deletions
|
|
@ -315,45 +315,19 @@ impl KbContextManager {
|
|||
// Create a temporary indexer with bot-specific config
|
||||
let indexer = KbIndexer::new(embedding_config, qdrant_config);
|
||||
|
||||
// Use the bot-specific indexer for search
|
||||
let search_results = indexer
|
||||
.search(collection_name, query, max_results)
|
||||
.await?;
|
||||
// Use the bot-specific indexer for search
|
||||
let search_results = indexer
|
||||
.search(collection_name, query, max_results * 3)
|
||||
.await?;
|
||||
|
||||
let mut kb_search_results = Vec::new();
|
||||
let mut total_tokens = 0;
|
||||
let deduplicated = self.deduplicate_by_document(search_results);
|
||||
let kb_search_results = self.filter_by_tokens(deduplicated, max_tokens);
|
||||
|
||||
for result in search_results {
|
||||
let tokens = estimate_tokens(&result.content);
|
||||
|
||||
if total_tokens + tokens > max_tokens {
|
||||
debug!(
|
||||
"Skipping result due to token limit ({} + {} > {})",
|
||||
total_tokens, tokens, max_tokens
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
if result.score < 0.3 {
|
||||
debug!("Skipping low-relevance result (score: {})", result.score);
|
||||
continue;
|
||||
}
|
||||
|
||||
kb_search_results.push(KbSearchResult {
|
||||
content: result.content,
|
||||
document_path: result.document_path,
|
||||
score: result.score,
|
||||
chunk_tokens: tokens,
|
||||
});
|
||||
|
||||
total_tokens += tokens;
|
||||
}
|
||||
|
||||
Ok(KbContext {
|
||||
kb_name: display_name.to_string(),
|
||||
search_results: kb_search_results,
|
||||
total_tokens,
|
||||
})
|
||||
Ok(KbContext {
|
||||
kb_name: display_name.to_string(),
|
||||
search_results: kb_search_results,
|
||||
total_tokens: 0,
|
||||
})
|
||||
}
|
||||
|
||||
async fn get_bot_id_by_name(&self, bot_name: &str) -> Result<Uuid> {
|
||||
|
|
@ -383,13 +357,55 @@ impl KbContextManager {
|
|||
|
||||
let search_results = self
|
||||
.kb_manager
|
||||
.search(bot_id, bot_name, kb_name, query, max_results)
|
||||
.search(bot_id, bot_name, kb_name, query, max_results * 3)
|
||||
.await?;
|
||||
|
||||
let deduplicated = self.deduplicate_by_document(search_results);
|
||||
let kb_search_results = self.filter_by_tokens(deduplicated, max_tokens);
|
||||
|
||||
Ok(KbContext {
|
||||
kb_name: kb_name.to_string(),
|
||||
search_results: kb_search_results,
|
||||
total_tokens: 0,
|
||||
})
|
||||
}
|
||||
|
||||
fn deduplicate_by_document(&self, results: Vec<crate::core::kb::SearchResult>) -> Vec<crate::core::kb::SearchResult> {
|
||||
use std::collections::HashMap;
|
||||
|
||||
let mut best_by_doc: HashMap<String, crate::core::kb::SearchResult> = HashMap::new();
|
||||
|
||||
for result in results {
|
||||
let doc_key = if result.document_path.is_empty() {
|
||||
format!("unknown_{}", result.content.len())
|
||||
} else {
|
||||
result.document_path.clone()
|
||||
};
|
||||
|
||||
best_by_doc
|
||||
.entry(doc_key)
|
||||
.and_modify(|existing| {
|
||||
if result.score > existing.score {
|
||||
*existing = result.clone();
|
||||
}
|
||||
})
|
||||
.or_insert(result);
|
||||
}
|
||||
|
||||
let mut results: Vec<_> = best_by_doc.into_values().collect();
|
||||
results.sort_by(|a, b| b.score.partial_cmp(&a.score).unwrap_or(std::cmp::Ordering::Equal));
|
||||
results
|
||||
}
|
||||
|
||||
fn filter_by_tokens(
|
||||
&self,
|
||||
results: Vec<crate::core::kb::SearchResult>,
|
||||
max_tokens: usize,
|
||||
) -> Vec<KbSearchResult> {
|
||||
let mut kb_search_results = Vec::new();
|
||||
let mut total_tokens = 0;
|
||||
|
||||
for result in search_results {
|
||||
for result in results {
|
||||
let tokens = estimate_tokens(&result.content);
|
||||
|
||||
if total_tokens + tokens > max_tokens {
|
||||
|
|
@ -400,7 +416,7 @@ impl KbContextManager {
|
|||
break;
|
||||
}
|
||||
|
||||
if result.score < 0.3 {
|
||||
if result.score < 0.25 {
|
||||
debug!("Skipping low-relevance result (score: {})", result.score);
|
||||
continue;
|
||||
}
|
||||
|
|
@ -415,11 +431,7 @@ impl KbContextManager {
|
|||
total_tokens += tokens;
|
||||
}
|
||||
|
||||
Ok(KbContext {
|
||||
kb_name: kb_name.to_string(),
|
||||
search_results: kb_search_results,
|
||||
total_tokens,
|
||||
})
|
||||
kb_search_results
|
||||
}
|
||||
|
||||
pub fn build_context_string(&self, kb_contexts: &[KbContext]) -> String {
|
||||
|
|
|
|||
|
|
@ -432,7 +432,7 @@ impl BotOrchestrator {
|
|||
if message.message_type == MessageType::TOOL_EXEC {
|
||||
let tool_name = message_content.trim();
|
||||
if !tool_name.is_empty() {
|
||||
info!("[TOOL_EXEC] Direct tool execution: {}", tool_name);
|
||||
info!("tool_exec: Direct tool execution: {}", tool_name);
|
||||
|
||||
// Get bot name from bot_id
|
||||
let bot_name = if let Ok(bot_uuid) = Uuid::parse_str(&message.bot_id) {
|
||||
|
|
@ -922,7 +922,7 @@ impl BotOrchestrator {
|
|||
let _handler = llm_models::get_handler(&model);
|
||||
|
||||
trace!("Using model handler for {}", model);
|
||||
trace!("LLM streaming started for session {}", session.id);
|
||||
info!("llm_start: Starting LLM streaming for session {}", session.id);
|
||||
trace!("Receiving LLM stream chunks...");
|
||||
let mut chunk_count: usize = 0;
|
||||
|
||||
|
|
@ -1314,31 +1314,30 @@ while let Some(chunk) = stream_rx.recv().await {
|
|||
}
|
||||
}
|
||||
|
||||
// DEBUG: Log LLM output for troubleshooting HTML rendering issues
|
||||
info!("llm_end: Streaming loop ended for session {}, chunk_count={}, full_response_len={}", session.id, chunk_count, full_response.len());
|
||||
|
||||
let has_html = full_response.contains("</") || full_response.contains("<!--");
|
||||
let has_div = full_response.contains("<div") || full_response.contains("</div>");
|
||||
let has_style = full_response.contains("<style");
|
||||
let is_truncated = !full_response.trim_end().ends_with("</div>") && has_div;
|
||||
let preview = if full_response.len() > 800 {
|
||||
format!("{}... ({} chars total)", &full_response[..800], full_response.len())
|
||||
format!("{}... ({} chars total)", full_response.split_at(800).0, full_response.len())
|
||||
} else {
|
||||
full_response.clone()
|
||||
};
|
||||
info!("[LLM_OUTPUT] session={} has_html={} has_div={} has_style={} is_truncated={} len={} preview=\"{}\"",
|
||||
info!("llm_output: session={} has_html={} has_div={} has_style={} is_truncated={} len={} preview=\"{}\"",
|
||||
session_id, has_html, has_div, has_style, is_truncated, full_response.len(),
|
||||
preview.replace('\n', "\\n"));
|
||||
|
||||
trace!("LLM stream complete. Full response: {}", full_response);
|
||||
|
||||
let plain_text = strip_markdown_local(&strip_html_local(&full_response));
|
||||
let plain_text_len = plain_text.len();
|
||||
let preview = if plain_text.len() > 100 {
|
||||
let history_preview = if plain_text.len() > 100 {
|
||||
format!("{}...", plain_text.split_at(100).0)
|
||||
} else {
|
||||
plain_text.clone()
|
||||
};
|
||||
info!("[HISTORY] Saving assistant message to history: session_id={}, user_id={}, content_len={}, preview={}",
|
||||
session.id, user_id, plain_text_len, preview);
|
||||
info!("history_save: session_id={} user_id={} content_len={} preview={}",
|
||||
session.id, user_id, plain_text_len, history_preview);
|
||||
|
||||
let state_for_save = self.state.clone();
|
||||
let plain_text_for_save = plain_text.clone();
|
||||
|
|
@ -1356,13 +1355,13 @@ while let Some(chunk) = stream_rx.recv().await {
|
|||
|
||||
match save_result {
|
||||
Ok(Ok(())) => {
|
||||
trace!("Assistant message saved to history for session {}", session_id_for_save);
|
||||
trace!("history_save: Assistant message saved for session {}", session_id_for_save);
|
||||
}
|
||||
Ok(Err(e)) => {
|
||||
error!("[HISTORY] Failed to save assistant message to history for session {}: {}", session_id_for_save, e);
|
||||
error!("history_save: Failed to save assistant message for session {}: {}", session_id_for_save, e);
|
||||
}
|
||||
Err(e) => {
|
||||
error!("[HISTORY] Spawn blocking failed for saving assistant message: {}", e);
|
||||
error!("history_save: Spawn blocking failed for session {}: {}", session_id_for_save, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -65,6 +65,8 @@ impl EmbeddingConfig {
|
|||
.get_config(_bot_id, "embedding-url", Some(""))
|
||||
.unwrap_or_default();
|
||||
|
||||
info!("EmbeddingConfig::from_bot_config - bot_id: {}, embedding_url: {}", _bot_id, embedding_url);
|
||||
|
||||
let embedding_model = config_manager
|
||||
.get_config(_bot_id, "embedding-model", Some("BAAI/bge-multilingual-gemma2"))
|
||||
.unwrap_or_else(|_| "BAAI/bge-multilingual-gemma2".to_string());
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue