Tauri 2 + Vue 3 + Vite 6 桌面应用,Rust workspace 含 13 个 crate (df-ai / df-storage / df-workflow / df-core / df-execute 等)。 核心能力:AI 聊天 agentic 循环(工具调用+人工审批)、工作流引擎、 任务/想法/项目/阶段管理、可追溯性,及配套前端组件。
6.6 KiB
6.6 KiB
df-ai - AI 集成模块
Provider 抽象层与流式响应处理
📋 模块概览
df-ai 负责 AI 功能的核心集成,支持多个 AI Provider,提供统一的接口和流式响应处理。
主要特性
- 多 Provider 支持(OpenAI、Anthropic、DeepSeek)
- 流式响应处理
- 工具调用支持
- 错误处理和重试机制
🏗️ 架构设计
核心组件
// Provider trait 定义
pub trait AIProvider: Send + Sync {
async fn chat_completion(&self, request: ChatRequest) -> Result<ChatResponse>;
async fn create_embedding(&self, text: &str) -> Result<Vec<f32>>;
}
// 流式响应处理
pub struct StreamProcessor {
event_sender: mpsc::UnboundedSender<StreamEvent>,
}
// 统一的 AI 服务
pub struct AIService {
providers: HashMap<String, Box<dyn AIProvider>>,
default_provider: String,
}
Provider 实现
- OpenAIProvider: OpenAI GPT 系列模型
- AnthropicProvider: Claude 系列模型
- DeepSeekProvider: DeepSeek 模型
🔧 使用方法
基础聊天
use df_ai::AIService;
let ai_service = AIService::new(config);
let request = ChatRequest {
model: "gpt-4".to_string(),
messages: vec![Message {
role: "user".to_string(),
content: "Hello, world!".to_string(),
}],
};
let response = ai_service.chat_completion(request).await?;
流式响应
use df_ai::stream_chat;
let (mut receiver, mut stream) = stream_chat(&ai_service, request).await?;
while let Some(event) = receiver.recv().await {
match event {
StreamEvent::Content(chunk) => {
print!("{}", chunk);
}
StreamEvent::Done => {
println!("\n完成");
}
StreamEvent::Error(e) => {
eprintln!("错误: {}", e);
}
}
}
工具调用
let request = ChatRequest {
model: "gpt-4".to_string(),
messages: vec![Message {
role: "user".to_string(),
content: "创建一个文件".to_string(),
}],
tools: vec![Tool {
r#type: "function".to_string(),
function: FunctionDef {
name: "create_file".to_string(),
description: "创建文件".to_string(),
parameters: Parameters {
r#type: "object".to_string(),
properties: serde_json::json!({
"path": {"type": "string"},
"content": {"type": "string"}
}),
required: vec!["path".to_string()],
},
},
}],
tool_choice: "auto".to_string(),
};
⚙️ 配置
Provider 配置
# config/ai.yaml
providers:
openai:
api_key: ${OPENAI_API_KEY}
base_url: "https://api.openai.com/v1"
model: "gpt-4"
max_tokens: 4000
temperature: 0.7
anthropic:
api_key: ${ANTHROPIC_API_KEY}
model: "claude-3-sonnet-20240229"
max_tokens: 4000
temperature: 0.7
deepseek:
api_key: ${DEEPSEEK_API_KEY}
model: "deepseek-chat"
max_tokens: 4000
temperature: 0.7
default_provider: "openai"
环境变量
export OPENAI_API_KEY="sk-your-key"
export ANTHROPIC_API_KEY="sk-ant-key"
export DEEPSEEK_API_KEY="your-key"
🔄 错误处理
错误类型
pub enum AIError {
APIError(String), // API 调用失败
Timeout, // 请求超时
RateLimit, // 达到速率限制
InvalidResponse, // 响应格式错误
ProviderNotFound, // Provider 不存在
ConfigurationError, // 配置错误
}
重试机制
let config = RetryConfig {
max_attempts: 3,
backoff: ExponentialBackoff::from_millis(1000),
retryable_errors: vec![
AIError::Timeout,
AIError::RateLimit,
],
};
let response = ai_service.chat_with_retry(request, &config).await?;
📊 性能优化
缓存机制
pub struct CachedAIService {
inner: AIService,
cache: Arc<Mutex<HashMap<String, ChatResponse>>>,
}
// 缓存键生成
fn cache_key(request: &ChatRequest) -> String {
format!("{:?}-{:?}", request.model, request.messages)
}
连接池
pub struct ConnectionPool {
connections: HashMap<String, Vec<Client>>,
max_connections: usize,
}
pub async fn get_client(&self, provider: &str) -> Result<Client> {
// 从连接池获取或创建新连接
}
🔍 监控与日志
请求追踪
pub struct RequestTracer {
request_id: String,
start_time: Instant,
metrics: RequestMetrics,
}
impl RequestTracer {
pub fn log_request(&self, provider: &str, duration: Duration) {
metrics.record_request(provider, duration);
}
}
指标收集
pub struct RequestMetrics {
total_requests: AtomicU64,
successful_requests: AtomicU64,
failed_requests: AtomicU64,
average_duration: AtomicDuration,
}
🧪 测试
单元测试
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_chat_completion() {
let ai_service = AIService::new(test_config());
let request = test_request();
let response = ai_service.chat_completion(request).await;
assert!(response.is_ok());
}
}
集成测试
#[tokio::test]
async fn test_multiple_providers() {
let providers = vec!["openai", "anthropic"];
for provider in providers {
let ai_service = AIService::new(config_for_provider(provider));
let response = test_chat(&ai_service).await;
assert!(response.is_ok(), "Provider {} failed", provider);
}
}
🚨 最佳实践
1. 错误处理
// ✅ 正确
match ai_service.chat_completion(request).await {
Ok(response) => handle_response(response),
Err(AIError::RateLimit) => wait_and_retry(),
Err(e) => log_error_and_notify(e),
}
// ❌ 错误 - 忽略错误
let _ = ai_service.chat_completion(request).await;
2. 资源管理
// ✅ 正确 - 使用连接池
let client = connection_pool.get_client("openai").await?;
// ❌ 错误 - 每次创建新连接
let client = Client::new(config);
3. 并发控制
// ✅ 正确 - 使用信号量
let semaphore = Arc::new(Semaphore::new(10));
let permit = semaphore.acquire().await?;
let response = ai_service.chat_completion(request).await;
// ❌ 错误 - 无限制并发
let handles: Vec<_> = requests.into_iter().map(|req| {
tokio::spawn(ai_service.chat_completion(req))
}).collect();
相关文档: