PicoBot/src/gateway/agent_prompt_provider.rs
oudecheng 0f60b02ede chore(log): 缩减 INFO 日志量,高频诊断日志降级/删除
1. 删除缓存诊断日志 4 处(openai.rs):排查已完结,字段已补齐,每次 LLM 调用都刷屏。
2. 删除 AgentPromptProvider 模型配置日志(agent_prompt_provider.rs):排查遗留,每次请求刷。
3. AgentFactory 创建日志 info→debug(agent_factory.rs):每轮对话刷,降级保留供偶发排查。
4. Calling tool / Tool calls detected info→debug(agent_loop.rs):每次工具调用都刷,全量参数打印开销大,tracing 在未启用级别时不评估字段。
5. LoadTaskMessages 3 条日志 info→debug(load_task_messages.rs):每次前端 trigger 都刷,一次 3 条。
6. 旧结果诊断日志 info→debug(execution.rs):每条消息首次 agent 迭代都触发。
7. pending subagents 日志 info→debug(processor.rs):子代理运行期高频率重复触发。
8. Updating current_session_id 仅变化时打(ws.rs):old==new 时每条消息都刷,无信息量。
编译通过,测试全绿。
2026-08-15 23:10:39 +08:00

157 lines
5.1 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use std::sync::Arc;
use crate::agent::{SystemPrompt, SystemPromptContext, SystemPromptProvider};
use crate::config::LLMProviderConfig;
use crate::gateway::prompt::{generate_system_environment_prompt, load_agent_prompt};
use crate::storage::PromptInjectionRepository;
/// Agent 提示词提供者
///
/// 负责提供来自 AGENT.md、MEMORY_SUMMARY.md 和 builtin 的系统提示词,
/// 以及动态生成的系统环境信息。
pub struct AgentPromptProvider {
/// 重新注入间隔(用户消息数)
_reinject_every: usize,
/// LLM 提供者配置(用于生成系统环境信息)
provider_config: LLMProviderConfig,
/// 会话持久化仓库(用于记录注入状态)
repository: Arc<dyn PromptInjectionRepository>,
}
impl AgentPromptProvider {
/// 创建新的 Agent 提示词提供者
pub fn new(
reinject_every: usize,
provider_config: LLMProviderConfig,
repository: Arc<dyn PromptInjectionRepository>,
) -> Self {
Self {
_reinject_every: reinject_every,
provider_config,
repository,
}
}
/// 判断是否应该注入提示词
///
/// 规则:每次处理用户消息都动态注入系统提示词
fn should_inject(&self, _context: &SystemPromptContext) -> bool {
// 每次消息都注入系统提示词
true
}
/// 记录注入事件
fn record_injection(&self, context: &SystemPromptContext) {
if let Some(session_id) = &context.session_id {
if let Err(e) = self.repository.mark_agent_prompt_reinjected(session_id) {
tracing::warn!(
session_id = ?session_id,
error = %e,
"Failed to mark agent prompt reinjected; injection counter may be inaccurate"
);
}
}
}
}
impl SystemPromptProvider for AgentPromptProvider {
fn build(&self, context: &SystemPromptContext) -> Option<SystemPrompt> {
// 检查是否需要注入
if !self.should_inject(context) {
return None;
}
// 加载 Agent 提示词AGENT.md + builtin + MEMORY_SUMMARY.md
let agent_prompt = load_agent_prompt().ok().flatten()?;
// 生成系统环境信息
let env_info = generate_system_environment_prompt(&self.provider_config);
// 记录注入事件
self.record_injection(context);
Some(SystemPrompt {
content: format!("{}\n\n{}", agent_prompt, env_info),
context: Some("agent_prompt".to_string()),
})
}
}
/// Agent 提示词提供者(简化版本,无持久化)
///
/// 适用于不需要记录注入状态的场景(如测试或一次性任务)。
pub struct SimpleAgentPromptProvider {
provider_config: LLMProviderConfig,
}
impl SimpleAgentPromptProvider {
/// 创建新的简单 Agent 提示词提供者
pub fn new(provider_config: LLMProviderConfig) -> Self {
Self { provider_config }
}
}
impl SystemPromptProvider for SimpleAgentPromptProvider {
fn build(&self, _context: &SystemPromptContext) -> Option<SystemPrompt> {
// 加载 Agent 提示词
let agent_prompt = load_agent_prompt().ok().flatten()?;
// 生成系统环境信息
let env_info = generate_system_environment_prompt(&self.provider_config);
Some(SystemPrompt {
content: format!("{}\n\n{}", agent_prompt, env_info),
context: Some("agent_prompt".to_string()),
})
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::collections::HashMap;
fn test_config() -> LLMProviderConfig {
LLMProviderConfig {
provider_type: "openai".to_string(),
name: "test".to_string(),
base_url: "http://localhost".to_string(),
api_key: "test-key".to_string(),
extra_headers: HashMap::new(),
llm_timeout_secs: 120,
memory_maintenance_timeout_secs: 600,
max_retries: 3,
model_id: "test-model".to_string(),
temperature: Some(0.0),
max_tokens: Some(32),
context_window_tokens: None,
model_extra: HashMap::new(),
max_tool_iterations: 1,
tool_result_max_chars: 100_000,
context_tool_result_trim_chars: 20_000,
max_images_in_context: 1,
max_image_age_rounds: 10,
}
}
fn test_context(user_count: usize, session_id: Option<&str>) -> SystemPromptContext {
SystemPromptContext {
session_id: session_id.map(|s| s.to_string()),
chat_id: "test-chat".to_string(),
user_message_count: user_count,
}
}
#[test]
fn test_simple_provider_builds_prompt() {
let provider = SimpleAgentPromptProvider::new(test_config());
let context = test_context(0, None);
// Simple provider always returns content
let result = provider.build(&context).unwrap();
assert!(result.content.contains("PicoBot"));
assert!(result.content.contains("操作系统:"));
assert_eq!(result.context, Some("agent_prompt".to_string()));
}
}