Tauri 2 + Vue 3 + Vite 6 桌面应用,Rust workspace 含 13 个 crate (df-ai / df-storage / df-workflow / df-core / df-execute 等)。 核心能力:AI 聊天 agentic 循环(工具调用+人工审批)、工作流引擎、 任务/想法/项目/阶段管理、可追溯性,及配套前端组件。
298 lines
6.6 KiB
Markdown
298 lines
6.6 KiB
Markdown
# df-ai - AI 集成模块
|
||
|
||
> Provider 抽象层与流式响应处理
|
||
|
||
## 📋 模块概览
|
||
|
||
`df-ai` 负责 AI 功能的核心集成,支持多个 AI Provider,提供统一的接口和流式响应处理。
|
||
|
||
### 主要特性
|
||
- 多 Provider 支持(OpenAI、Anthropic、DeepSeek)
|
||
- 流式响应处理
|
||
- 工具调用支持
|
||
- 错误处理和重试机制
|
||
|
||
## 🏗️ 架构设计
|
||
|
||
### 核心组件
|
||
```rust
|
||
// 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 模型
|
||
|
||
## 🔧 使用方法
|
||
|
||
### 基础聊天
|
||
```rust
|
||
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?;
|
||
```
|
||
|
||
### 流式响应
|
||
```rust
|
||
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);
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 工具调用
|
||
```rust
|
||
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 配置
|
||
```yaml
|
||
# 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"
|
||
```
|
||
|
||
### 环境变量
|
||
```bash
|
||
export OPENAI_API_KEY="sk-your-key"
|
||
export ANTHROPIC_API_KEY="sk-ant-key"
|
||
export DEEPSEEK_API_KEY="your-key"
|
||
```
|
||
|
||
## 🔄 错误处理
|
||
|
||
### 错误类型
|
||
```rust
|
||
pub enum AIError {
|
||
APIError(String), // API 调用失败
|
||
Timeout, // 请求超时
|
||
RateLimit, // 达到速率限制
|
||
InvalidResponse, // 响应格式错误
|
||
ProviderNotFound, // Provider 不存在
|
||
ConfigurationError, // 配置错误
|
||
}
|
||
```
|
||
|
||
### 重试机制
|
||
```rust
|
||
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?;
|
||
```
|
||
|
||
## 📊 性能优化
|
||
|
||
### 缓存机制
|
||
```rust
|
||
pub struct CachedAIService {
|
||
inner: AIService,
|
||
cache: Arc<Mutex<HashMap<String, ChatResponse>>>,
|
||
}
|
||
|
||
// 缓存键生成
|
||
fn cache_key(request: &ChatRequest) -> String {
|
||
format!("{:?}-{:?}", request.model, request.messages)
|
||
}
|
||
```
|
||
|
||
### 连接池
|
||
```rust
|
||
pub struct ConnectionPool {
|
||
connections: HashMap<String, Vec<Client>>,
|
||
max_connections: usize,
|
||
}
|
||
|
||
pub async fn get_client(&self, provider: &str) -> Result<Client> {
|
||
// 从连接池获取或创建新连接
|
||
}
|
||
```
|
||
|
||
## 🔍 监控与日志
|
||
|
||
### 请求追踪
|
||
```rust
|
||
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);
|
||
}
|
||
}
|
||
```
|
||
|
||
### 指标收集
|
||
```rust
|
||
pub struct RequestMetrics {
|
||
total_requests: AtomicU64,
|
||
successful_requests: AtomicU64,
|
||
failed_requests: AtomicU64,
|
||
average_duration: AtomicDuration,
|
||
}
|
||
```
|
||
|
||
## 🧪 测试
|
||
|
||
### 单元测试
|
||
```rust
|
||
#[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());
|
||
}
|
||
}
|
||
```
|
||
|
||
### 集成测试
|
||
```rust
|
||
#[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. 错误处理
|
||
```rust
|
||
// ✅ 正确
|
||
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. 资源管理
|
||
```rust
|
||
// ✅ 正确 - 使用连接池
|
||
let client = connection_pool.get_client("openai").await?;
|
||
|
||
// ❌ 错误 - 每次创建新连接
|
||
let client = Client::new(config);
|
||
```
|
||
|
||
### 3. 并发控制
|
||
```rust
|
||
// ✅ 正确 - 使用信号量
|
||
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();
|
||
```
|
||
|
||
---
|
||
|
||
**相关文档**:
|
||
- [df-storage - 存储层](./df-storage-存储层.md)
|
||
- [df-workflow - 工作流引擎](./df-workflow-工作流引擎.md)
|
||
- [df-nodes - 节点集合](./df-nodes-节点集合.md) |