478 lines
14 KiB
Markdown
478 lines
14 KiB
Markdown
# Gemini SDK 开发提示词
|
||
|
||
## 项目概述
|
||
|
||
基于 `apps\desktop\src-tauri\src\infrastructure\gemini_service.rs` 的现有实现,创建一个独立的 Rust crate `gemini-sdk`,提供简洁易用的 Gemini AI 服务接口。
|
||
|
||
## 核心设计目标
|
||
|
||
1. **简化接口**: 提供统一的消息发送接口,支持文本+附件输入
|
||
2. **Agent 系统**: 支持多个 AI Agent,每个 Agent 有独立的 system prompt 和配置
|
||
3. **多轮对话**: 支持会话管理和历史记录
|
||
4. **类型安全**: 强类型设计,编译时错误检查
|
||
5. **易于集成**: 最小化外部依赖,易于在其他项目中使用
|
||
|
||
## 技术架构
|
||
|
||
### 依赖管理
|
||
```toml
|
||
[dependencies]
|
||
tokio = { version = "1.0", features = ["full"] }
|
||
reqwest = { version = "0.11", features = ["json", "multipart"] }
|
||
serde = { version = "1.0", features = ["derive"] }
|
||
serde_json = "1.0"
|
||
anyhow = "1.0"
|
||
uuid = { version = "1.0", features = ["v4"] }
|
||
chrono = { version = "0.4", features = ["serde"] }
|
||
base64 = "0.22"
|
||
rusqlite = { version = "0.31", features = ["bundled", "chrono"] }
|
||
```
|
||
|
||
### 核心数据结构
|
||
|
||
```rust
|
||
// SDK 主体
|
||
pub struct GeminiSDK {
|
||
service: GeminiService,
|
||
conversation_repo: Option<Arc<ConversationRepository>>,
|
||
agents: HashMap<String, Agent>,
|
||
}
|
||
|
||
// Agent 定义
|
||
pub struct Agent {
|
||
pub id: String,
|
||
pub name: String,
|
||
pub system_prompt: String,
|
||
pub config: AgentConfig,
|
||
pub created_at: DateTime<Utc>,
|
||
}
|
||
|
||
pub struct AgentConfig {
|
||
pub temperature: f32,
|
||
pub max_tokens: u32,
|
||
pub timeout: u64,
|
||
pub enable_conversation: bool,
|
||
}
|
||
|
||
// 消息结构
|
||
pub struct MessageRequest {
|
||
pub text: String,
|
||
pub attachments: Vec<Attachment>,
|
||
pub agent_id: Option<String>,
|
||
pub session_id: Option<String>,
|
||
pub config: Option<MessageConfig>,
|
||
}
|
||
|
||
pub struct MessageResponse {
|
||
pub content: String,
|
||
pub session_id: String,
|
||
pub message_id: Option<String>,
|
||
pub agent_id: Option<String>,
|
||
}
|
||
|
||
// 附件定义
|
||
pub struct Attachment {
|
||
pub path: String,
|
||
pub mime_type: Option<String>,
|
||
}
|
||
|
||
// 会话管理
|
||
pub struct ConversationSession {
|
||
pub session_id: String,
|
||
pub title: Option<String>,
|
||
pub created_at: DateTime<Utc>,
|
||
}
|
||
|
||
pub struct HistoryMessage {
|
||
pub role: MessageRole,
|
||
pub content: String,
|
||
pub timestamp: DateTime<Utc>,
|
||
pub attachments: Vec<String>,
|
||
}
|
||
```
|
||
|
||
## 核心功能接口
|
||
|
||
### 1. SDK 初始化
|
||
```rust
|
||
impl GeminiSDK {
|
||
// 基础初始化
|
||
pub fn new() -> Result<Self>;
|
||
|
||
// 支持多轮对话
|
||
pub fn with_conversation_support(db_path: Option<String>) -> Result<Self>;
|
||
|
||
// 自定义配置
|
||
pub fn with_config(config: GeminiConfig) -> Result<Self>;
|
||
}
|
||
```
|
||
|
||
### 2. 核心消息接口
|
||
```rust
|
||
impl GeminiSDK {
|
||
// 主要方法:发送消息+附件,获得回复
|
||
pub async fn send_message(&mut self, request: MessageRequest) -> Result<MessageResponse>;
|
||
}
|
||
```
|
||
|
||
### 3. Agent 管理
|
||
```rust
|
||
impl GeminiSDK {
|
||
// Agent CRUD
|
||
pub fn create_agent(&mut self, name: String, system_prompt: String, config: Option<AgentConfig>) -> Result<Agent>;
|
||
pub fn get_agent(&self, agent_id: &str) -> Option<&Agent>;
|
||
pub fn list_agents(&self) -> Vec<&Agent>;
|
||
pub fn update_agent(&mut self, agent_id: &str, name: Option<String>, system_prompt: Option<String>, config: Option<AgentConfig>) -> Result<()>;
|
||
pub fn delete_agent(&mut self, agent_id: &str) -> Result<()>;
|
||
|
||
// 预设 Agent
|
||
pub fn create_outfit_advisor_agent(&mut self) -> Result<Agent>;
|
||
pub fn create_video_analyst_agent(&mut self) -> Result<Agent>;
|
||
pub fn create_general_assistant_agent(&mut self) -> Result<Agent>;
|
||
}
|
||
```
|
||
|
||
### 4. 会话管理
|
||
```rust
|
||
impl GeminiSDK {
|
||
// 会话 CRUD
|
||
pub async fn create_session(&self, title: Option<String>) -> Result<ConversationSession>;
|
||
pub async fn get_session(&self, session_id: &str) -> Result<Option<ConversationSession>>;
|
||
pub async fn list_sessions(&self) -> Result<Vec<ConversationSession>>;
|
||
pub async fn delete_session(&self, session_id: &str) -> Result<()>;
|
||
|
||
// 历史记录
|
||
pub async fn get_conversation_history(&self, session_id: &str, limit: Option<u32>) -> Result<Vec<HistoryMessage>>;
|
||
pub async fn clear_conversation_history(&self, session_id: &str) -> Result<()>;
|
||
}
|
||
```
|
||
|
||
### 5. 便捷构造函数
|
||
```rust
|
||
impl Attachment {
|
||
pub fn new(path: impl Into<String>) -> Self;
|
||
pub fn with_mime_type(path: impl Into<String>, mime_type: impl Into<String>) -> Self;
|
||
}
|
||
|
||
impl MessageRequest {
|
||
pub fn text_only(text: impl Into<String>) -> Self;
|
||
pub fn with_attachments(text: impl Into<String>, attachments: Vec<Attachment>) -> Self;
|
||
pub fn with_agent(text: impl Into<String>, agent_id: impl Into<String>) -> Self;
|
||
}
|
||
```
|
||
|
||
## 实现要求
|
||
|
||
### 1. 文件结构
|
||
```
|
||
cargos/gemini-sdk/
|
||
├── Cargo.toml
|
||
├── src/
|
||
│ ├── lib.rs # 主入口
|
||
│ ├── sdk.rs # SDK 主体实现
|
||
│ ├── agent.rs # Agent 相关
|
||
│ ├── conversation.rs # 会话管理
|
||
│ ├── attachment.rs # 附件处理
|
||
│ ├── error.rs # 错误定义
|
||
│ └── presets/ # 预设 Agent
|
||
│ ├── mod.rs
|
||
│ ├── outfit_advisor.rs
|
||
│ ├── video_analyst.rs
|
||
│ └── general_assistant.rs
|
||
├── examples/
|
||
│ ├── basic_usage.rs
|
||
│ ├── agent_demo.rs
|
||
│ └── conversation_demo.rs
|
||
└── tests/
|
||
├── integration_tests.rs
|
||
└── agent_tests.rs
|
||
```
|
||
|
||
### 2. 核心实现逻辑
|
||
|
||
#### 消息发送流程
|
||
1. 检查是否指定 Agent,获取对应配置和 system prompt
|
||
2. 处理附件:根据文件类型选择上传(视频)或编码(图片)
|
||
3. 构建 Gemini API 请求,包含 system prompt
|
||
4. 如果启用会话,使用多轮对话模式;否则使用单轮模式
|
||
5. 调用底层 GeminiService 方法
|
||
6. 返回格式化的响应
|
||
|
||
#### Agent 系统
|
||
1. 内存中维护 Agent 映射表
|
||
2. 每个 Agent 包含独立的 system prompt 和配置
|
||
3. 提供预设的专业 Agent(穿搭顾问、视频分析师等)
|
||
4. 支持动态创建和管理自定义 Agent
|
||
|
||
#### 会话管理
|
||
1. 可选的 SQLite 数据库支持
|
||
2. 自动会话创建和历史记录保存
|
||
3. 支持会话标题和元数据管理
|
||
4. 历史消息检索和清理
|
||
|
||
### 3. 错误处理
|
||
```rust
|
||
#[derive(Debug, thiserror::Error)]
|
||
pub enum SDKError {
|
||
#[error("配置错误: {0}")]
|
||
Config(String),
|
||
|
||
#[error("Agent 不存在: {0}")]
|
||
AgentNotFound(String),
|
||
|
||
#[error("会话错误: {0}")]
|
||
Session(String),
|
||
|
||
#[error("附件处理错误: {0}")]
|
||
Attachment(String),
|
||
|
||
#[error("网络错误: {0}")]
|
||
Network(#[from] reqwest::Error),
|
||
|
||
#[error("数据库错误: {0}")]
|
||
Database(#[from] rusqlite::Error),
|
||
|
||
#[error("Gemini 服务错误: {0}")]
|
||
GeminiService(#[from] anyhow::Error),
|
||
}
|
||
```
|
||
|
||
### 4. 使用示例
|
||
```rust
|
||
// 基础使用
|
||
let mut sdk = GeminiSDK::with_conversation_support(None)?;
|
||
|
||
// 创建穿搭顾问 Agent
|
||
let agent = sdk.create_outfit_advisor_agent()?;
|
||
|
||
// 发送消息
|
||
let request = MessageRequest {
|
||
text: "分析这张穿搭图片".to_string(),
|
||
attachments: vec![Attachment::new("./outfit.jpg")],
|
||
agent_id: Some(agent.id),
|
||
session_id: None,
|
||
config: None,
|
||
};
|
||
|
||
let response = sdk.send_message(request).await?;
|
||
println!("回复: {}", response.content);
|
||
```
|
||
|
||
## 开发指导
|
||
|
||
### 1. 代码复用策略
|
||
- 直接复用 `gemini_service.rs` 中的核心逻辑
|
||
- 提取通用的配置、错误处理和网络请求代码
|
||
- 简化接口,隐藏内部复杂性
|
||
|
||
### 2. 测试策略
|
||
- 单元测试:各个组件的独立功能
|
||
- 集成测试:完整的消息发送流程
|
||
- 示例代码:展示各种使用场景
|
||
|
||
### 3. 文档要求
|
||
- 完整的 API 文档
|
||
- 使用示例和最佳实践
|
||
- 错误处理指南
|
||
- 性能优化建议
|
||
|
||
### 4. 性能考虑
|
||
- 连接池复用
|
||
- 合理的超时设置
|
||
- 内存使用优化
|
||
- 异步操作支持
|
||
|
||
## 交付标准
|
||
|
||
1. **功能完整性**: 所有设计的接口都能正常工作
|
||
2. **代码质量**: 遵循 Rust 最佳实践,通过 clippy 检查
|
||
3. **测试覆盖**: 核心功能有完整的测试覆盖
|
||
4. **文档完善**: 清晰的 API 文档和使用示例
|
||
5. **易用性**: 简洁的接口,最小化学习成本
|
||
|
||
## 详细实现指南
|
||
|
||
### 1. 从现有代码迁移的关键组件
|
||
|
||
#### 需要复用的核心结构
|
||
```rust
|
||
// 从 gemini_service.rs 复用
|
||
pub struct GeminiConfig { /* 保持原有字段 */ }
|
||
pub struct GenerateContentRequest { /* 保持原有结构 */ }
|
||
pub struct ContentPart { /* 保持原有结构 */ }
|
||
pub enum Part { /* 保持原有枚举 */ }
|
||
pub struct GenerationConfig { /* 保持原有结构 */ }
|
||
```
|
||
|
||
#### 需要复用的核心方法
|
||
- `get_access_token()` - 访问令牌管理
|
||
- `upload_video_file()` - 视频文件上传
|
||
- `generate_content_with_request()` - 内容生成
|
||
- `query_llm_with_grounding_multi_turn()` - 多轮对话
|
||
- `extract_json_from_response()` - JSON 解析
|
||
|
||
### 2. 简化的内部服务层
|
||
|
||
```rust
|
||
// 简化的内部服务,封装复杂逻辑
|
||
struct InternalGeminiService {
|
||
config: GeminiConfig,
|
||
client: reqwest::Client,
|
||
access_token: Option<String>,
|
||
token_expires_at: Option<u64>,
|
||
}
|
||
|
||
impl InternalGeminiService {
|
||
// 复用原有的核心方法,但简化接口
|
||
async fn send_request(&mut self, parts: Vec<Part>, config: GenerationConfig, system_prompt: Option<String>) -> Result<String>;
|
||
async fn upload_file(&mut self, path: &str) -> Result<String>;
|
||
async fn send_multipart_request(&mut self, parts: Vec<Part>, config: GenerationConfig, system_prompt: Option<String>, session_id: Option<String>) -> Result<String>;
|
||
}
|
||
```
|
||
|
||
### 4. 错误恢复和重试机制
|
||
|
||
```rust
|
||
impl GeminiSDK {
|
||
async fn send_message_with_retry(&mut self, request: MessageRequest, max_retries: u32) -> Result<MessageResponse> {
|
||
let mut last_error = None;
|
||
|
||
for attempt in 0..max_retries {
|
||
match self.send_message_internal(request.clone()).await {
|
||
Ok(response) => return Ok(response),
|
||
Err(e) => {
|
||
last_error = Some(e);
|
||
if attempt < max_retries - 1 {
|
||
let delay = std::time::Duration::from_secs(2_u64.pow(attempt));
|
||
tokio::time::sleep(delay).await;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
Err(last_error.unwrap())
|
||
}
|
||
}
|
||
```
|
||
|
||
### 5. 配置管理
|
||
|
||
```rust
|
||
impl GeminiSDK {
|
||
pub fn from_env() -> Result<Self> {
|
||
let config = GeminiConfig {
|
||
base_url: std::env::var("GEMINI_BASE_URL").unwrap_or_else(|_| "https://bowongai-dev--bowong-ai-video-gemini-fastapi-webapp.modal.run".to_string()),
|
||
bearer_token: std::env::var("GEMINI_BEARER_TOKEN").unwrap_or_else(|_| "bowong7777".to_string()),
|
||
// ... 其他配置
|
||
};
|
||
|
||
Self::with_config(config)
|
||
}
|
||
}
|
||
```
|
||
|
||
### 6. 完整的使用示例
|
||
|
||
```rust
|
||
#[tokio::main]
|
||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||
// 1. 初始化 SDK
|
||
let mut sdk = GeminiSDK::with_conversation_support(None)?;
|
||
|
||
|
||
// 3. 穿搭分析示例
|
||
let outfit_request = MessageRequest {
|
||
text: "请分析这张穿搭图片,给出专业的搭配建议".to_string(),
|
||
attachments: vec![Attachment::new("./examples/outfit.jpg")],
|
||
agent_id: Some(outfit_agent.id.clone()),
|
||
session_id: None,
|
||
config: None,
|
||
};
|
||
|
||
let outfit_response = sdk.send_message(outfit_request).await?;
|
||
println!("穿搭顾问分析:\n{}", outfit_response.content);
|
||
|
||
// 4. 视频分析示例
|
||
let video_request = MessageRequest {
|
||
text: "请分析这个视频的内容质量和改进建议".to_string(),
|
||
attachments: vec![Attachment::new("./examples/video.mp4")],
|
||
agent_id: Some(video_agent.id),
|
||
session_id: None,
|
||
config: Some(MessageConfig {
|
||
temperature: Some(0.6),
|
||
max_tokens: Some(12000),
|
||
timeout: Some(180),
|
||
}),
|
||
};
|
||
|
||
let video_response = sdk.send_message(video_request).await?;
|
||
println!("视频分析报告:\n{}", video_response.content);
|
||
|
||
// 5. 多轮对话示例
|
||
let session = sdk.create_session(Some("穿搭咨询".to_string())).await?;
|
||
|
||
let follow_up = MessageRequest {
|
||
text: "基于刚才的分析,我想要更正式一些的搭配方案".to_string(),
|
||
attachments: vec![],
|
||
agent_id: Some(outfit_agent.id),
|
||
session_id: Some(session.session_id.clone()),
|
||
config: None,
|
||
};
|
||
|
||
let follow_response = sdk.send_message(follow_up).await?;
|
||
println!("后续建议:\n{}", follow_response.content);
|
||
|
||
// 6. 查看对话历史
|
||
let history = sdk.get_conversation_history(&session.session_id, Some(10)).await?;
|
||
for msg in history {
|
||
println!("{}: {}", msg.role, msg.content);
|
||
}
|
||
|
||
Ok(())
|
||
}
|
||
```
|
||
|
||
## 质量保证要求
|
||
|
||
### 1. 代码规范
|
||
- 使用 `cargo fmt` 格式化代码
|
||
- 通过 `cargo clippy` 静态检查
|
||
- 添加适当的文档注释
|
||
- 遵循 Rust 命名约定
|
||
|
||
### 2. 测试要求
|
||
```rust
|
||
#[cfg(test)]
|
||
mod tests {
|
||
use super::*;
|
||
|
||
#[tokio::test]
|
||
async fn test_basic_message_sending() {
|
||
// 测试基础消息发送功能
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn test_agent_management() {
|
||
// 测试 Agent 创建和管理
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn test_conversation_flow() {
|
||
// 测试多轮对话流程
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn test_attachment_processing() {
|
||
// 测试附件处理
|
||
}
|
||
}
|
||
```
|
||
|
||
### 3. 文档要求
|
||
- 每个公共接口都要有详细的文档注释
|
||
- 提供完整的使用示例
|
||
- 包含错误处理指南
|
||
- 性能和最佳实践说明
|
||
|
||
请基于这个详细的设计方案和实现指南,创建一个高质量、易用、功能完整的 Gemini SDK crate。
|