chore: 增强日志追踪与代码格式化
- daemon: 添加 LLM 回合开始/结束标记日志,工具执行结果追踪 - daemon: 发送消费者日志增强(显示完整文本、截断用户 ID) - conversation: 移除日志截断,输出完整工具调用参数和结果 - deepseek: 代码格式化,预留请求/响应摘要日志 - 删除 systemd/ias.service
This commit is contained in:
+69
-27
@@ -109,9 +109,9 @@ pub async fn run(database: &Arc<Database>, memory_store: &Arc<MemoryStore>) {
|
||||
info!("Daemon 已启动");
|
||||
|
||||
// 4-6. 审批管理器、工具列表、模型配置
|
||||
let approval_manager = Arc::new(ApprovalManager::new(
|
||||
Some(Arc::new(database.pool().clone())),
|
||||
));
|
||||
let approval_manager = Arc::new(ApprovalManager::new(Some(Arc::new(
|
||||
database.pool().clone(),
|
||||
))));
|
||||
let tools_list = build_tools_list();
|
||||
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());
|
||||
@@ -349,8 +349,6 @@ async fn llm_consumer_loop(
|
||||
context_token,
|
||||
approved_tool,
|
||||
} => {
|
||||
info!("LLM Consumer: user={} text={:.60}", user_id, text);
|
||||
|
||||
// 加载数据
|
||||
ctx.memory_store.load_if_needed(&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 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 uid = uid.clone();
|
||||
let corr = corr;
|
||||
@@ -465,11 +464,6 @@ async fn llm_consumer_loop(
|
||||
result,
|
||||
context_token,
|
||||
} => {
|
||||
info!(
|
||||
"LLM Consumer: 工具结果回喂 user={} tool={}",
|
||||
user_id, tool_name
|
||||
);
|
||||
|
||||
// 从缓存恢复会话,注入工具结果并恢复 LLM 循环
|
||||
let should_resume = {
|
||||
let mut map = sessions.lock().await;
|
||||
@@ -532,6 +526,8 @@ async fn run_llm_round(
|
||||
sessions: &Arc<Mutex<HashMap<Uuid, (Conversation, Instant)>>>,
|
||||
enqueue: &EnqueueHandle,
|
||||
) {
|
||||
info!("══════════════════════════════════════════════════");
|
||||
info!("🔄 LLM 回合开始 user={} text={}", user_id, text);
|
||||
let result = {
|
||||
let map = sessions.lock().await;
|
||||
let conv = match map.get(&correlation_id) {
|
||||
@@ -575,6 +571,8 @@ async fn resume_llm_round(
|
||||
sessions: &Arc<Mutex<HashMap<Uuid, (Conversation, Instant)>>>,
|
||||
enqueue: &EnqueueHandle,
|
||||
) {
|
||||
info!("══════════════════════════════════════════════════");
|
||||
info!("🔄 LLM 恢复 user={}", user_id);
|
||||
let result = {
|
||||
let map = sessions.lock().await;
|
||||
let conv = match map.get(&correlation_id) {
|
||||
@@ -636,6 +634,7 @@ async fn handle_chat_result(
|
||||
enqueue.enqueue(msg).await;
|
||||
}
|
||||
sessions.lock().await.remove(&correlation_id);
|
||||
info!("✅ LLM 回合结束 user={}", user_id);
|
||||
}
|
||||
|
||||
// ─── Tool Consumer ───
|
||||
@@ -660,7 +659,10 @@ async fn tool_consumer_loop(
|
||||
context_token,
|
||||
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) {
|
||||
@@ -734,7 +736,9 @@ fn execute_tool<'a>(
|
||||
// 上下文工具
|
||||
match name {
|
||||
"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" => {
|
||||
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();
|
||||
}
|
||||
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" => {
|
||||
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 {
|
||||
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" => {
|
||||
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() {
|
||||
return "请提供 content 参数".to_string();
|
||||
}
|
||||
return ctx
|
||||
let result = ctx
|
||||
.memory_store
|
||||
.update_for(user_id, memory_id, content)
|
||||
.await;
|
||||
tracing::info!("🔧 execute_tool: update_memory({}) → {}", memory_id, result);
|
||||
return result;
|
||||
}
|
||||
"read_summaries" => {
|
||||
let sums = load_summaries(&ctx.db, user_id).await;
|
||||
if sums.is_empty() {
|
||||
return "暂无历史摘要".to_string();
|
||||
}
|
||||
return sums
|
||||
.iter()
|
||||
let result = if sums.is_empty() {
|
||||
"暂无历史摘要".to_string()
|
||||
} else {
|
||||
sums.iter()
|
||||
.enumerate()
|
||||
.map(|(i, s)| format!("{}. {}", i + 1, s))
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n---\n");
|
||||
.join("\n---\n")
|
||||
};
|
||||
tracing::info!("🔧 execute_tool: read_summaries → {}条", sums.len());
|
||||
return result;
|
||||
}
|
||||
"query_capabilities" => {
|
||||
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" => {
|
||||
// 解包 {name, prompt} → 提取目标工具名和参数,递归派发
|
||||
@@ -807,6 +824,11 @@ fn execute_tool<'a>(
|
||||
}
|
||||
let target_args = serde_json::to_string(&crate::tools::unpack_call_params(&cp))
|
||||
.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;
|
||||
}
|
||||
@@ -815,8 +837,19 @@ fn execute_tool<'a>(
|
||||
|
||||
// 内置工具注册表
|
||||
match crate::tools::execute(name, arguments).await {
|
||||
Some(r) => r.output,
|
||||
None => format!("未知工具: {}", name),
|
||||
Some(r) => {
|
||||
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,
|
||||
} => {
|
||||
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
|
||||
.client
|
||||
@@ -844,7 +882,11 @@ async fn send_consumer_loop(
|
||||
.await
|
||||
{
|
||||
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(
|
||||
ctx.db.pool(),
|
||||
"outbound",
|
||||
|
||||
@@ -313,7 +313,7 @@ impl Conversation {
|
||||
calls.len(),
|
||||
calls
|
||||
.iter()
|
||||
.map(|c| format!("{}({:.80})", c.function.name, c.function.arguments))
|
||||
.map(|c| format!("{}({})", c.function.name, c.function.arguments))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
);
|
||||
@@ -344,7 +344,7 @@ impl Conversation {
|
||||
continue;
|
||||
}
|
||||
|
||||
tracing::info!("📦 {} → {:.150}", tc.function.name, result);
|
||||
tracing::info!("📦 {} → {}", tc.function.name, result);
|
||||
self.session.lock().await.add_tool_result(
|
||||
&tc.id,
|
||||
&tc.function.name,
|
||||
|
||||
+18
-3
@@ -154,6 +154,13 @@ async fn stream_deepseek(
|
||||
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_reasoning = String::new();
|
||||
let mut usage: Option<Usage> = None;
|
||||
@@ -216,7 +223,8 @@ async fn stream_deepseek(
|
||||
|
||||
// 检查最后的 buffer
|
||||
if !buf.trim().is_empty()
|
||||
&& let Some(parsed) = parse_chat_chunk(buf.trim()) {
|
||||
&& let Some(parsed) = parse_chat_chunk(buf.trim())
|
||||
{
|
||||
match parsed {
|
||||
ParsedChunk::Text(t) => full_text.push_str(&t),
|
||||
ParsedChunk::ToolCallDelta {
|
||||
@@ -225,8 +233,7 @@ async fn stream_deepseek(
|
||||
name,
|
||||
arguments,
|
||||
} => {
|
||||
let entry =
|
||||
tool_call_builders
|
||||
let entry = tool_call_builders
|
||||
.entry(index)
|
||||
.or_insert((None, None, String::new()));
|
||||
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
|
||||
.send(StreamChunk::Done {
|
||||
text: full_text,
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user