chore: 增强日志追踪与代码格式化

- daemon: 添加 LLM 回合开始/结束标记日志,工具执行结果追踪
- daemon: 发送消费者日志增强(显示完整文本、截断用户 ID)
- conversation: 移除日志截断,输出完整工具调用参数和结果
- deepseek: 代码格式化,预留请求/响应摘要日志
- 删除 systemd/ias.service
This commit is contained in:
2026-06-16 22:53:19 +08:00
parent f608c27f8a
commit e20cd19e57
4 changed files with 181 additions and 141 deletions
+69 -27
View File
@@ -109,9 +109,9 @@ pub async fn run(database: &Arc<Database>, memory_store: &Arc<MemoryStore>) {
info!("Daemon 已启动"); info!("Daemon 已启动");
// 4-6. 审批管理器、工具列表、模型配置 // 4-6. 审批管理器、工具列表、模型配置
let approval_manager = Arc::new(ApprovalManager::new( let approval_manager = Arc::new(ApprovalManager::new(Some(Arc::new(
Some(Arc::new(database.pool().clone())), database.pool().clone(),
)); ))));
let tools_list = build_tools_list(); let tools_list = build_tools_list();
let system_prompt = std::env::var("WEIXIN_LLM_SYSTEM_PROMPT").unwrap_or_else(|_| String::new()); let system_prompt = std::env::var("WEIXIN_LLM_SYSTEM_PROMPT").unwrap_or_else(|_| String::new());
let model = std::env::var("DEEPSEEK_MODEL").unwrap_or_else(|_| "deepseek-v4-flash".to_string()); let model = std::env::var("DEEPSEEK_MODEL").unwrap_or_else(|_| "deepseek-v4-flash".to_string());
@@ -349,8 +349,6 @@ async fn llm_consumer_loop(
context_token, context_token,
approved_tool, approved_tool,
} => { } => {
info!("LLM Consumer: user={} text={:.60}", user_id, text);
// 加载数据 // 加载数据
ctx.memory_store.load_if_needed(&user_id).await; ctx.memory_store.load_if_needed(&user_id).await;
let history = load_history(&ctx.db, &user_id).await; let history = load_history(&ctx.db, &user_id).await;
@@ -399,7 +397,8 @@ async fn llm_consumer_loop(
let session = conv.session(); let session = conv.session();
let approved_tool = approved_tool.clone(); let approved_tool = approved_tool.clone();
let executor: ToolExecutor = Arc::new(move |name: &str, args_json: &str, tc_id: &str| { let executor: ToolExecutor =
Arc::new(move |name: &str, args_json: &str, tc_id: &str| {
let eq = eq.clone(); let eq = eq.clone();
let uid = uid.clone(); let uid = uid.clone();
let corr = corr; let corr = corr;
@@ -465,11 +464,6 @@ async fn llm_consumer_loop(
result, result,
context_token, context_token,
} => { } => {
info!(
"LLM Consumer: 工具结果回喂 user={} tool={}",
user_id, tool_name
);
// 从缓存恢复会话,注入工具结果并恢复 LLM 循环 // 从缓存恢复会话,注入工具结果并恢复 LLM 循环
let should_resume = { let should_resume = {
let mut map = sessions.lock().await; let mut map = sessions.lock().await;
@@ -532,6 +526,8 @@ async fn run_llm_round(
sessions: &Arc<Mutex<HashMap<Uuid, (Conversation, Instant)>>>, sessions: &Arc<Mutex<HashMap<Uuid, (Conversation, Instant)>>>,
enqueue: &EnqueueHandle, enqueue: &EnqueueHandle,
) { ) {
info!("══════════════════════════════════════════════════");
info!("🔄 LLM 回合开始 user={} text={}", user_id, text);
let result = { let result = {
let map = sessions.lock().await; let map = sessions.lock().await;
let conv = match map.get(&correlation_id) { let conv = match map.get(&correlation_id) {
@@ -575,6 +571,8 @@ async fn resume_llm_round(
sessions: &Arc<Mutex<HashMap<Uuid, (Conversation, Instant)>>>, sessions: &Arc<Mutex<HashMap<Uuid, (Conversation, Instant)>>>,
enqueue: &EnqueueHandle, enqueue: &EnqueueHandle,
) { ) {
info!("══════════════════════════════════════════════════");
info!("🔄 LLM 恢复 user={}", user_id);
let result = { let result = {
let map = sessions.lock().await; let map = sessions.lock().await;
let conv = match map.get(&correlation_id) { let conv = match map.get(&correlation_id) {
@@ -636,6 +634,7 @@ async fn handle_chat_result(
enqueue.enqueue(msg).await; enqueue.enqueue(msg).await;
} }
sessions.lock().await.remove(&correlation_id); sessions.lock().await.remove(&correlation_id);
info!("✅ LLM 回合结束 user={}", user_id);
} }
// ─── Tool Consumer ─── // ─── Tool Consumer ───
@@ -660,7 +659,10 @@ async fn tool_consumer_loop(
context_token, context_token,
approved, approved,
} => { } => {
info!("Tool Consumer: user={} tool={}", user_id, tool_name); info!(
"Tool Consumer: user={} tool={} args={}",
user_id, tool_name, arguments
);
// 高风险工具 → 审批(除非已被用户批准) // 高风险工具 → 审批(除非已被用户批准)
if !approved && crate::tools::is_high_risk(&tool_name) { if !approved && crate::tools::is_high_risk(&tool_name) {
@@ -734,7 +736,9 @@ fn execute_tool<'a>(
// 上下文工具 // 上下文工具
match name { match name {
"read_memories" => { "read_memories" => {
return ctx.memory_store.read_for(user_id, None).await; let result = ctx.memory_store.read_for(user_id, None).await;
tracing::info!("🔧 execute_tool: read_memories → {}", result);
return result;
} }
"write_memory" => { "write_memory" => {
let params: serde_json::Value = serde_json::from_str(arguments).unwrap_or_default(); let params: serde_json::Value = serde_json::from_str(arguments).unwrap_or_default();
@@ -743,7 +747,9 @@ fn execute_tool<'a>(
return "请提供 content 参数".to_string(); return "请提供 content 参数".to_string();
} }
ctx.memory_store.write_for(user_id, content).await; ctx.memory_store.write_for(user_id, content).await;
return format!("已添加长期记忆: {}", content); let result = format!("已添加长期记忆: {}", content);
tracing::info!("🔧 execute_tool: write_memory → {}", result);
return result;
} }
"delete_memory" => { "delete_memory" => {
let params: serde_json::Value = serde_json::from_str(arguments).unwrap_or_default(); let params: serde_json::Value = serde_json::from_str(arguments).unwrap_or_default();
@@ -754,7 +760,9 @@ fn execute_tool<'a>(
if memory_id <= 0 { if memory_id <= 0 {
return "请提供有效的 memory_id 参数".to_string(); return "请提供有效的 memory_id 参数".to_string();
} }
return ctx.memory_store.delete_for(user_id, memory_id).await; let result = ctx.memory_store.delete_for(user_id, memory_id).await;
tracing::info!("🔧 execute_tool: delete_memory({}) → {}", memory_id, result);
return result;
} }
"update_memory" => { "update_memory" => {
let params: serde_json::Value = serde_json::from_str(arguments).unwrap_or_default(); let params: serde_json::Value = serde_json::from_str(arguments).unwrap_or_default();
@@ -769,26 +777,35 @@ fn execute_tool<'a>(
if content.is_empty() { if content.is_empty() {
return "请提供 content 参数".to_string(); return "请提供 content 参数".to_string();
} }
return ctx let result = ctx
.memory_store .memory_store
.update_for(user_id, memory_id, content) .update_for(user_id, memory_id, content)
.await; .await;
tracing::info!("🔧 execute_tool: update_memory({}) → {}", memory_id, result);
return result;
} }
"read_summaries" => { "read_summaries" => {
let sums = load_summaries(&ctx.db, user_id).await; let sums = load_summaries(&ctx.db, user_id).await;
if sums.is_empty() { let result = if sums.is_empty() {
return "暂无历史摘要".to_string(); "暂无历史摘要".to_string()
} } else {
return sums sums.iter()
.iter()
.enumerate() .enumerate()
.map(|(i, s)| format!("{}. {}", i + 1, s)) .map(|(i, s)| format!("{}. {}", i + 1, s))
.collect::<Vec<_>>() .collect::<Vec<_>>()
.join("\n---\n"); .join("\n---\n")
};
tracing::info!("🔧 execute_tool: read_summaries → {}条", sums.len());
return result;
} }
"query_capabilities" => { "query_capabilities" => {
let specs = crate::tools::specs(); let specs = crate::tools::specs();
return crate::tools::build_capability_guide(&specs); let result = crate::tools::build_capability_guide(&specs);
tracing::info!(
"🔧 execute_tool: query_capabilities → {}个工具",
specs.len()
);
return result;
} }
"call_capability" => { "call_capability" => {
// 解包 {name, prompt} → 提取目标工具名和参数,递归派发 // 解包 {name, prompt} → 提取目标工具名和参数,递归派发
@@ -807,6 +824,11 @@ fn execute_tool<'a>(
} }
let target_args = serde_json::to_string(&crate::tools::unpack_call_params(&cp)) let target_args = serde_json::to_string(&crate::tools::unpack_call_params(&cp))
.unwrap_or_default(); .unwrap_or_default();
tracing::info!(
"🔧 execute_tool: call_capability → {} args={}",
target_name,
target_args
);
// 递归派发 // 递归派发
return execute_tool(&target_name, &target_args, ctx, user_id).await; return execute_tool(&target_name, &target_args, ctx, user_id).await;
} }
@@ -815,8 +837,19 @@ fn execute_tool<'a>(
// 内置工具注册表 // 内置工具注册表
match crate::tools::execute(name, arguments).await { match crate::tools::execute(name, arguments).await {
Some(r) => r.output, Some(r) => {
None => format!("未知工具: {}", name), tracing::info!(
"🔧 execute_tool: {} → success={} output={}",
name,
r.success,
r.output
);
r.output
}
None => {
tracing::warn!("🔧 execute_tool: 未知工具 {}", name);
format!("未知工具: {}", name)
}
} }
}) })
} }
@@ -836,7 +869,12 @@ async fn send_consumer_loop(
context_token, context_token,
} => { } => {
let user_id = &msg.channel.user_id; let user_id = &msg.channel.user_id;
info!("Send Consumer: user={} text_len={}", user_id, text.len()); info!(
"Send Consumer: user={} text_len={} text={}",
user_id,
text.len(),
text
);
match ctx match ctx
.client .client
@@ -844,7 +882,11 @@ async fn send_consumer_loop(
.await .await
{ {
Ok(sent_id) => { Ok(sent_id) => {
info!("回复成功 user={} msg_id={}", user_id, sent_id); info!(
"回复成功 user={} msg_id={}",
user_id.chars().take(5).collect::<String>(),
sent_id
);
let _ = crate::db::models::insert_chat_record( let _ = crate::db::models::insert_chat_record(
ctx.db.pool(), ctx.db.pool(),
"outbound", "outbound",
+2 -2
View File
@@ -313,7 +313,7 @@ impl Conversation {
calls.len(), calls.len(),
calls calls
.iter() .iter()
.map(|c| format!("{}({:.80})", c.function.name, c.function.arguments)) .map(|c| format!("{}({})", c.function.name, c.function.arguments))
.collect::<Vec<_>>() .collect::<Vec<_>>()
.join(", ") .join(", ")
); );
@@ -344,7 +344,7 @@ impl Conversation {
continue; continue;
} }
tracing::info!("📦 {} → {:.150}", tc.function.name, result); tracing::info!("📦 {} → {}", tc.function.name, result);
self.session.lock().await.add_tool_result( self.session.lock().await.add_tool_result(
&tc.id, &tc.id,
&tc.function.name, &tc.function.name,
+18 -3
View File
@@ -154,6 +154,13 @@ async fn stream_deepseek(
return Err(format!("HTTP {}: {}", status, text)); return Err(format!("HTTP {}: {}", status, text));
} }
// 记录请求摘要
// tracing::info!(
// "🌐 LLM 请求: model={} messages_count={}",
// body.get("model").and_then(|v| v.as_str()).unwrap_or("?"),
// body.get("messages").and_then(|v| v.as_array()).map(|a| a.len()).unwrap_or(0),
// );
let mut full_text = String::new(); let mut full_text = String::new();
let mut full_reasoning = String::new(); let mut full_reasoning = String::new();
let mut usage: Option<Usage> = None; let mut usage: Option<Usage> = None;
@@ -216,7 +223,8 @@ async fn stream_deepseek(
// 检查最后的 buffer // 检查最后的 buffer
if !buf.trim().is_empty() if !buf.trim().is_empty()
&& let Some(parsed) = parse_chat_chunk(buf.trim()) { && let Some(parsed) = parse_chat_chunk(buf.trim())
{
match parsed { match parsed {
ParsedChunk::Text(t) => full_text.push_str(&t), ParsedChunk::Text(t) => full_text.push_str(&t),
ParsedChunk::ToolCallDelta { ParsedChunk::ToolCallDelta {
@@ -225,8 +233,7 @@ async fn stream_deepseek(
name, name,
arguments, arguments,
} => { } => {
let entry = let entry = tool_call_builders
tool_call_builders
.entry(index) .entry(index)
.or_insert((None, None, String::new())); .or_insert((None, None, String::new()));
if let Some(call_id) = id { if let Some(call_id) = id {
@@ -267,6 +274,14 @@ async fn stream_deepseek(
) )
}; };
// 记录完整的响应输出
// tracing::info!(
// "🌐 LLM 响应: text_len={} tool_calls={} usage={:?}",
// full_text.len(),
// tool_calls.as_ref().map(|tc| tc.len()).unwrap_or(0),
// usage
// );
let _ = tx let _ = tx
.send(StreamChunk::Done { .send(StreamChunk::Done {
text: full_text, text: full_text,
-17
View File
@@ -1,17 +0,0 @@
[Unit]
Description=iAs - 微信 AI 智能助手
After=network.target postgresql.service
[Service]
Type=simple
User=xiao
WorkingDirectory=/home/xiao/project/iAs
EnvironmentFile=/home/xiao/project/iAs/.env
ExecStart=/home/xiao/project/iAs/target/release/iAs service
Restart=on-failure
RestartSec=10
StandardOutput=null
StandardError=null
[Install]
WantedBy=multi-user.target