版本: v0.2.0
更新时间: 2026-02-18
Rust:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
rustup default stable开发工具:
# 代码格式化
rustup component add rustfmt
# 代码检查
rustup component add clippy
# IDE 支持
cargo install rust-analyzer可选服务:
# Middleware Demo (Redis + Qdrant)
docker-compose -f docker-compose.middleware-demo.yml up -dCompose 文件说明:
docker-compose.standalone.yml: 单机全栈docker-compose.cluster.yml: 双 gateway 集群演示docker-compose.middleware-demo.yml: 中间件 demo / 故障注入场景
服务器信息:
- 地址:
root@104.194.91.83 - 端口:
26974 - 认证: SSH Key(已配置免密登录)
- Docker: ✅ 已安装
- 用途: 测试部署、性能测试
连接服务器:
ssh root@104.194.91.83 -p 26974部署到服务器:
# 一键部署
./deploy-remote.sh
# 手动同步
rsync -avz -e "ssh -p 26974" . root@104.194.91.83:/opt/memoryos/访问服务:
- Gateway: http://104.194.91.83:8080
- Health: http://104.194.91.83:8080/health
- Metrics: http://104.194.91.83:8080/metrics
注意: 此服务器仅供开发测试使用,使用 SSH Key 认证,安全可靠。
git clone https://github.com/BAI-LAB/MemoryOS.git
cd MemoryOS/MemoryOS-Rustcp config.example.toml config.toml
# 编辑 config.toml 填入你的 API keys# 检查编译
cargo check --workspace
# 运行测试
cargo test --workspace
# 启动服务
cargo run --package memoryos-gateway
# 可选:仅在启用异步记忆管道时启动 Worker(单节点可不启)
# export MEMORYOS_ASYNC_MEMORY_PIPELINE=true
# cargo run --package memoryos-worker
# 启动中间件(本地调试)
docker-compose -f docker-compose.middleware-demo.yml up -dMemoryOS-Rust/
├── crates/
│ ├── memoryos-core/ # 核心业务逻辑
│ │ ├── src/
│ │ │ ├── config.rs # 配置管理
│ │ │ ├── error.rs # 错误定义
│ │ │ ├── health.rs # 健康检查
│ │ │ └── memory/ # 记忆系统
│ │ └── Cargo.toml
│ │
│ ├── memoryos-ports/ # 端口定义(接口)
│ │ ├── src/
│ │ │ ├── llm.rs # LLM 适配器接口
│ │ │ └── memory.rs # 记忆存储接口
│ │ └── Cargo.toml
│ │
│ ├── memoryos-adapters/ # 适配器实现
│ │ ├── src/
│ │ │ ├── llm/ # LLM 适配器
│ │ │ │ ├── openai.rs
│ │ │ │ ├── gemini.rs
│ │ │ │ ├── claude.rs
│ │ │ │ ├── ollama.rs
│ │ │ │ ├── deepseek.rs
│ │ │ │ ├── openrouter.rs
│ │ │ │ └── azure_openai.rs
│ │ │ └── memory/ # 存储适配器
│ │ │ ├── redis.rs
│ │ │ ├── qdrant.rs
│ │ │ └── manager.rs
│ │ └── Cargo.toml
│ │
│ ├── memoryos-gateway/ # HTTP 网关
│ ├── src/
│ │ ├── main.rs # 入口
│ │ ├── router.rs # 3-Tier 路由
│ │ └── routes/ # API 路由
│ │ ├── chat.rs
│ │ ├── memory.rs
│ │ └── health.rs
│ └── Cargo.toml
│
│ └── memoryos-worker/ # 异步记忆 Worker
│ ├── src/
│ │ └── main.rs # Redis Stream consumer
│ └── Cargo.toml
│
├── config.toml # 配置文件
├── Cargo.toml # Workspace 配置
└── docs/ # 文档
┌─────────────────────────────────────────────┐
│ Gateway (HTTP Layer) │
│ ┌─────────────────────────────────────┐ │
│ │ Routes: /chat, /memory, /health │ │
│ └─────────────────────────────────────┘ │
└─────────────────┬───────────────────────────┘
│
┌─────────────────▼───────────────────────────┐
│ Core (Business Logic) │
│ ┌──────────────┐ ┌─────────────────┐ │
│ │ LLM Router │ │ Memory Manager │ │
│ │ (3-Tier) │ │ (Short/Mid/ │ │
│ │ │ │ Long-term) │ │
│ └──────────────┘ └─────────────────┘ │
└─────────────────┬───────────────────────────┘
│
┌─────────────────▼───────────────────────────┐
│ Ports (Interfaces) │
│ ┌──────────────┐ ┌─────────────────┐ │
│ │ LlmAdapter │ │ MemoryStorage │ │
│ │ trait │ │ trait │ │
│ └──────────────┘ └─────────────────┘ │
└─────────────────┬───────────────────────────┘
│
┌─────────────────▼───────────────────────────┐
│ Adapters (Implementations) │
│ ┌──────────────┐ ┌─────────────────┐ │
│ │ OpenAI │ │ Redis │ │
│ │ Gemini │ │ Qdrant │ │
│ │ Claude │ │ Noop (Fallback) │ │
│ │ Ollama │ │ │ │
│ │ DeepSeek │ │ │ │
│ │ OpenRouter │ │ │ │
│ │ Azure OpenAI │ │ │ │
│ └──────────────┘ └─────────────────┘ │
└─────────────────────────────────────────────┘
1. 端口(Ports):
- 定义业务接口
- 与具体实现解耦
- 位于
memoryos-ports
2. 适配器(Adapters):
- 实现端口接口
- 对接外部服务
- 位于
memoryos-adapters
3. 核心(Core):
- 业务逻辑
- 不依赖外部实现
- 位于
memoryos-core
4. 网关(Gateway):
- HTTP 接口
- 路由和中间件
- 位于
memoryos-gateway
5. Worker:
- 异步消费
chat_log - 幂等去重 + DLQ 兜底
- 位于
memoryos-worker
格式化:
cargo fmt --allLint 检查:
cargo clippy --all-targets --all-features -- -D warnings文件名: snake_case.rs
// ✅ 正确
src/llm_adapter.rs
src/memory_manager.rs
// ❌ 错误
src/LLMAdapter.rs
src/memoryManager.rs类型名: PascalCase
// ✅ 正确
struct ChatRequest { }
enum HealthMode { }
trait LlmAdapter { }
// ❌ 错误
struct chat_request { }
enum health_mode { }函数名: snake_case
// ✅ 正确
fn get_response() { }
async fn chat_stream() { }
// ❌ 错误
fn GetResponse() { }
fn chatStream() { }常量: SCREAMING_SNAKE_CASE
// ✅ 正确
const MAX_RETRIES: u32 = 3;
const DEFAULT_TIMEOUT: Duration = Duration::from_secs(30);
// ❌ 错误
const maxRetries: u32 = 3;
const default_timeout: Duration = Duration::from_secs(30);禁止 unwrap/expect:
// ❌ 错误 - 会 panic
let value = some_option.unwrap();
let result = some_result.expect("failed");
// ✅ 正确 - 返回 Result
let value = some_option.ok_or(AppError::NotFound("value".into()))?;
let result = some_result.map_err(|e| AppError::InternalError(e.to_string()))?;统一错误类型:
// 所有公共函数返回 Result<T, AppError>
pub async fn chat(&self, request: ChatRequest) -> Result<ChatResponse, AppError> {
// ...
}错误转换:
impl From<reqwest::Error> for AppError {
fn from(err: reqwest::Error) -> Self {
AppError::ExternalServiceError(err.to_string())
}
}使用 async/await:
#[async_trait]
pub trait LlmAdapter: Send + Sync {
async fn chat(&self, request: ChatRequest) -> Result<ChatResponse, AppError>;
}避免阻塞:
// ❌ 错误 - 阻塞异步运行时
std::thread::sleep(Duration::from_secs(1));
// ✅ 正确 - 异步等待
tokio::time::sleep(Duration::from_secs(1)).await;使用 tracing:
use tracing::{info, warn, error, debug};
// 信息日志
info!("Request processed successfully");
// 警告日志
warn!("Redis connection failed, using fallback");
// 错误日志
error!("Failed to call LLM: {}", err);
// 调试日志
debug!("Request body: {:?}", request);结构化日志:
info!(
method = %request.method,
path = %request.path,
status = response.status,
duration_ms = duration.as_millis(),
"Request completed"
);- 启动中间件:
docker-compose -f docker-compose.middleware-demo.yml up -d - 启动 gateway:
cargo run -p memoryos-gateway - 默认单节点无需 worker(同步路径可用)。
- 若要验证异步路径:
export MEMORYOS_ASYNC_MEMORY_PIPELINE=true并启动cargo run -p memoryos-worker - 调用
/v1/memory/add或redis-cli XADD chat_log ...验证异步消费。
- 启动
docker-compose.cluster.yml做双 gateway 演练。 - 启动多个 worker,保持同一
MEMORYOS_WORKER_GROUP。 - 每个 worker 设置唯一
MEMORYOS_WORKER_CONSUMER。 - 检查
chat_log积压与chat_log:dlq增长趋势。
- 事件字段变更必须保持至少一版向后兼容。
event_id语义变更必须同步更新 gateway/worker/docs/tests。- 重试策略变更必须明确 ACK 与 DLQ 分界条件。
# 需要本机可用 redis-cli
export MEMORYOS_ASYNC_MEMORY_PIPELINE=true
./scripts/smoke_async_pipeline.sh一键 Demo(自动拉起中间件 + gateway + worker):
./scripts/demo_async_pipeline.shDLQ 回放:
DRY_RUN=1 COUNT=20 ./scripts/replay_dlq.sh
DRY_RUN=0 COUNT=20 ./scripts/replay_dlq.sh测试模块:
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_config_load() {
let config = Config::from_file("config.example.toml").unwrap();
assert_eq!(config.server.port, 8080);
}
#[tokio::test]
async fn test_health_check() {
let status = HealthStatus::new();
assert_eq!(status.mode, HealthMode::FullyOperational);
}
}运行测试:
# 所有测试
cargo test --workspace
# 单个包
cargo test --package memoryos-core
# 单个测试
cargo test test_config_load
# 显示输出
cargo test -- --nocapture测试文件 (tests/integration_test.rs):
use memoryos_gateway::*;
#[tokio::test]
async fn test_chat_api() {
let app = create_app().await;
let response = app
.oneshot(
Request::builder()
.method("POST")
.uri("/v1/chat/completions")
.header("content-type", "application/json")
.body(Body::from(r#"{"model":"gpt-4o-mini","messages":[]}"#))
.unwrap()
)
.await
.unwrap();
assert_eq!(response.status(), StatusCode::OK);
}Mock LLM Adapter:
struct MockLlmAdapter;
#[async_trait]
impl LlmAdapter for MockLlmAdapter {
async fn chat(&self, _request: ChatRequest) -> Result<ChatResponse, AppError> {
Ok(ChatResponse {
id: "test".into(),
model: "mock".into(),
choices: vec![],
})
}
fn name(&self) -> &str {
"mock"
}
}# 安装 tarpaulin
cargo install cargo-tarpaulin
# 生成覆盖率报告
cargo tarpaulin --workspace --out Html# 在 GitHub 上 Fork
# 克隆你的 Fork
git clone https://github.com/YOUR_USERNAME/MemoryOS.git
cd MemoryOS/MemoryOS-Rustgit checkout -b feature/your-feature-name遵循规范:
- ✅ 代码格式化:
cargo fmt - ✅ Lint 检查:
cargo clippy - ✅ 测试通过:
cargo test - ✅ 文档更新
提交信息:
# 格式: <type>: <description>
git commit -m "feat: add streaming support"
git commit -m "fix: resolve Gemini API key leak"
git commit -m "docs: update API documentation"类型:
feat- 新功能fix- 修复 bugdocs- 文档更新style- 代码格式refactor- 重构test- 测试chore- 构建/工具
git push origin feature/your-feature-namePR 标题:
feat: Add streaming support for chat API
PR 描述:
## 变更说明
- 添加 `chat_stream` 方法到 LlmAdapter trait
- 实现 OpenAI 流式响应
- 更新 Gateway 支持 SSE
## 测试
- [x] 单元测试通过
- [x] 集成测试通过
- [x] 手动测试流式 API
## 相关 Issue
Closes #123响应反馈:
- 及时回复评论
- 修改代码
- 更新测试
合并要求:
- ✅ 所有测试通过
- ✅ Code review 通过
- ✅ 无冲突
- ✅ 文档更新
1. 定义 Adapter:
// crates/memoryos-adapters/src/llm/new_llm.rs
pub struct NewLlmAdapter {
client: reqwest::Client,
api_key: String,
base_url: String,
}
#[async_trait]
impl LlmAdapter for NewLlmAdapter {
async fn chat(&self, request: ChatRequest) -> Result<ChatResponse, AppError> {
// 实现调用逻辑
}
fn name(&self) -> &str {
"new_llm"
}
}2. 注册到 Router:
// crates/memoryos-gateway/src/router.rs
pub struct LlmRouter {
new_llm: Arc<dyn LlmAdapter>,
// ...
}3. 添加配置:
# config.toml
[llm]
new_llm_api_key = "..."
new_llm_base_url = "..."4. 添加测试:
#[tokio::test]
async fn test_new_llm_adapter() {
// ...
}1. 定义路由:
// crates/memoryos-gateway/src/routes/new_route.rs
pub async fn new_endpoint(
State(state): State<Arc<AppState>>,
Json(request): Json<NewRequest>,
) -> Result<Json<NewResponse>, AppError> {
// 实现逻辑
Ok(Json(response))
}2. 注册路由:
// crates/memoryos-gateway/src/routes/mod.rs
pub fn create_routes(state: Arc<AppState>) -> Router {
Router::new()
.route("/v1/new", post(new_endpoint))
// ...
}3. 添加测试:
#[tokio::test]
async fn test_new_endpoint() {
// ...
}RUST_LOG=debug cargo runrust-gdb target/debug/memoryos-gateway# 安装 flamegraph
cargo install flamegraph
# 生成火焰图
cargo flamegraph- Rust 官方文档: https://doc.rust-lang.org/
- Tokio 文档: https://tokio.rs/
- Axum 文档: https://docs.rs/axum/
- 项目 GitHub: https://github.com/BAI-LAB/MemoryOS
最后更新: 2026-02-17