Skip to content

Commit ff974eb

Browse files
zhonghao luzhonghao lu
authored andcommitted
refactor database model for agent management
1 parent 7c977aa commit ff974eb

7 files changed

Lines changed: 816 additions & 2 deletions

File tree

python/scripts/init_database.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#!/usr/bin/env python3
2+
"""Standalone database initialization script for ValueCell."""
3+
4+
import sys
5+
import os
6+
from pathlib import Path
7+
8+
# Add the project root to Python path
9+
project_root = Path(__file__).parent.parent
10+
sys.path.insert(0, str(project_root))
11+
12+
# Now import from valuecell
13+
from valuecell.server.db.init_db import main
14+
15+
if __name__ == "__main__":
16+
main()
Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
# ValueCell 数据库初始化
2+
3+
这个目录包含了 ValueCell Server 的数据库相关代码,包括模型定义、连接管理和初始化脚本。
4+
5+
## 目录结构
6+
7+
```
8+
db/
9+
├── __init__.py # 数据库包初始化
10+
├── connection.py # 数据库连接和会话管理
11+
├── init_db.py # 数据库初始化脚本
12+
├── models/ # 数据库模型
13+
│ ├── __init__.py
14+
│ ├── base.py # 基础模型类
15+
│ └── agent.py # Agent模型
16+
└── README.md # 本文档
17+
```
18+
19+
## 数据库配置
20+
21+
数据库配置在 `valuecell/server/config/settings.py` 中定义:
22+
23+
- **DATABASE_URL**: 数据库连接URL,默认为 `sqlite:///./valuecell.db`
24+
- **DB_ECHO**: 是否输出SQL日志,默认为 `false`
25+
26+
## 数据库模型
27+
28+
### Agent模型 (Agent)
29+
Agent模型存储了ValueCell系统中所有可用AI代理的信息:
30+
31+
**基本信息**
32+
- `name`: 唯一的代理标识符
33+
- `display_name`: 人类可读的显示名称
34+
- `description`: 代理功能和用途的详细描述
35+
- `url`: 代理服务的基础URL
36+
- `version`: 代理版本号
37+
38+
**状态管理**
39+
- `enabled`: 代理是否启用
40+
- `is_active`: 代理是否活跃可用
41+
42+
**功能描述**
43+
- `capabilities`: JSON格式的功能描述(如流式传输、推送通知等)
44+
- `agent_metadata`: 额外的元数据(作者、标签、支持的功能等)
45+
- `config`: 代理特定的配置参数
46+
47+
**性能跟踪**
48+
- `last_health_check`: 最后一次健康检查时间
49+
- `total_requests`: 处理的总请求数
50+
- `success_rate`: 成功率百分比
51+
52+
**时间戳**
53+
- `created_at`: 创建时间
54+
- `updated_at`: 更新时间
55+
56+
## 数据库初始化
57+
58+
### 使用方法
59+
60+
1. **基本初始化**
61+
```bash
62+
cd /path/to/valuecell/python
63+
python3 -m valuecell.server.db.init_db
64+
```
65+
66+
2. **强制重新初始化**
67+
```bash
68+
python3 -m valuecell.server.db.init_db --force
69+
```
70+
71+
3. **详细日志输出**
72+
```bash
73+
python3 -m valuecell.server.db.init_db --verbose
74+
```
75+
76+
4. **使用独立脚本**
77+
```bash
78+
python3 scripts/init_database.py
79+
```
80+
81+
### 初始化过程
82+
83+
1. **检查数据库文件**:验证SQLite数据库文件是否存在
84+
2. **创建数据库文件**:如果不存在则创建新的数据库文件
85+
3. **创建表结构**:根据模型定义创建agents表
86+
4. **初始化Agent数据**
87+
-`configs/agent_cards/` 目录加载所有JSON配置文件
88+
- 为每个配置文件创建对应的Agent记录
89+
- 支持更新现有Agent的配置信息
90+
5. **验证初始化**:确认数据库连接和表结构正确
91+
92+
### Agent配置文件
93+
94+
初始化脚本会自动加载 `configs/agent_cards/` 目录下的所有JSON配置文件:
95+
96+
**配置文件示例**
97+
```json
98+
{
99+
"name": "TradingAgentsAdapter",
100+
"url": "http://localhost:10002",
101+
"description": "TradingAgents - Multi-agent trading analysis system",
102+
"capabilities": {
103+
"streaming": true,
104+
"push_notifications": false
105+
},
106+
"metadata": {
107+
"version": "1.0.0",
108+
"author": "ValueCell Team",
109+
"tags": ["trading", "analysis", "multi-agent"],
110+
"supported_tickers": ["AAPL", "GOOGL", "MSFT"],
111+
"supported_analysts": ["market", "social", "news"]
112+
}
113+
}
114+
```
115+
116+
**当前支持的Agent**
117+
- `AIHedgeFundAgent`: AI对冲基金代理
118+
- `Sec13FundAgent`: SEC 13F基金分析代理
119+
- `TradingAgentsAdapter`: 多代理交易分析系统
120+
121+
## 在代码中使用
122+
123+
### 获取数据库会话
124+
125+
```python
126+
from valuecell.server.db import get_db, Agent
127+
128+
# 在FastAPI路由中使用依赖注入
129+
@app.get("/api/agents")
130+
def get_agents(db: Session = Depends(get_db)):
131+
return db.query(Agent).filter(Agent.enabled == True).all()
132+
```
133+
134+
### 直接使用数据库管理器
135+
136+
```python
137+
from valuecell.server.db import get_database_manager, Agent
138+
139+
db_manager = get_database_manager()
140+
session = db_manager.get_session()
141+
142+
try:
143+
# 获取所有启用的代理
144+
agents = session.query(Agent).filter(Agent.enabled == True).all()
145+
146+
# 获取特定代理
147+
trading_agent = session.query(Agent).filter(Agent.name == "TradingAgentsAdapter").first()
148+
149+
# 更新代理状态
150+
if trading_agent:
151+
trading_agent.is_active = True
152+
session.commit()
153+
finally:
154+
session.close()
155+
```
156+
157+
### 程序化初始化
158+
159+
```python
160+
from valuecell.server.db import init_database
161+
162+
# 初始化数据库
163+
success = init_database(force=False)
164+
if success:
165+
print("数据库初始化成功")
166+
else:
167+
print("数据库初始化失败")
168+
```
169+
170+
## 注意事项
171+
172+
1. **密码安全**:默认管理员用户的密码是占位符,在生产环境中需要替换为正确的哈希密码
173+
2. **数据库备份**:SQLite数据库文件应该定期备份
174+
3. **权限管理**:确保数据库文件有适当的文件系统权限
175+
4. **环境变量**:可以通过环境变量 `DATABASE_URL` 自定义数据库连接
176+
177+
## 故障排除
178+
179+
### 常见问题
180+
181+
1. **权限错误**:确保对数据库文件目录有写权限
182+
2. **模块导入错误**:确保在正确的Python环境中运行
183+
3. **数据库锁定**:确保没有其他进程正在使用数据库文件
184+
185+
### 重置数据库
186+
187+
如果需要完全重置数据库:
188+
189+
```bash
190+
# 删除现有数据库文件
191+
rm valuecell.db
192+
193+
# 重新初始化
194+
python3 -m valuecell.server.db.init_db
195+
```
196+
197+
或者使用强制重新初始化:
198+
199+
```bash
200+
python3 -m valuecell.server.db.init_db --force
201+
```
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
"""Database package for ValueCell Server."""
2+
3+
from .connection import (
4+
DatabaseManager,
5+
get_database_manager,
6+
get_db,
7+
)
8+
from .init_db import DatabaseInitializer, init_database
9+
from .models import *
10+
11+
__all__ = [
12+
# Connection management
13+
"DatabaseManager",
14+
"get_database_manager",
15+
"get_db",
16+
# Database initialization
17+
"DatabaseInitializer",
18+
"init_database",
19+
]
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
"""Database connection and session management for ValueCell Server."""
2+
3+
import os
4+
from typing import Generator
5+
from sqlalchemy import create_engine, Engine
6+
from sqlalchemy.orm import sessionmaker, Session
7+
from sqlalchemy.pool import StaticPool
8+
9+
from ..config.settings import get_settings
10+
from .models.base import Base
11+
12+
13+
class DatabaseManager:
14+
"""Database connection and session manager."""
15+
16+
def __init__(self):
17+
"""Initialize database manager."""
18+
self.settings = get_settings()
19+
self.engine: Engine = None
20+
self.SessionLocal = None
21+
self._initialize_engine()
22+
23+
def _initialize_engine(self) -> None:
24+
"""Initialize database engine."""
25+
database_config = self.settings.get_database_config()
26+
27+
# SQLite specific configuration
28+
connect_args = {}
29+
if database_config["url"].startswith("sqlite"):
30+
connect_args = {
31+
"check_same_thread": False,
32+
"timeout": 20,
33+
}
34+
35+
self.engine = create_engine(
36+
database_config["url"],
37+
echo=database_config["echo"],
38+
connect_args=connect_args,
39+
poolclass=StaticPool
40+
if database_config["url"].startswith("sqlite")
41+
else None,
42+
)
43+
44+
self.SessionLocal = sessionmaker(
45+
autocommit=False, autoflush=False, bind=self.engine
46+
)
47+
48+
def get_engine(self) -> Engine:
49+
"""Get database engine."""
50+
return self.engine
51+
52+
def create_tables(self) -> None:
53+
"""Create all tables defined in models."""
54+
Base.metadata.create_all(bind=self.engine)
55+
56+
def drop_tables(self) -> None:
57+
"""Drop all tables."""
58+
Base.metadata.drop_all(bind=self.engine)
59+
60+
def get_session(self) -> Session:
61+
"""Get a new database session."""
62+
return self.SessionLocal()
63+
64+
def get_db_session(self) -> Generator[Session, None, None]:
65+
"""Get database session for dependency injection."""
66+
db = self.SessionLocal()
67+
try:
68+
yield db
69+
finally:
70+
db.close()
71+
72+
73+
# Global database manager instance
74+
_db_manager: DatabaseManager = None
75+
76+
77+
def get_database_manager() -> DatabaseManager:
78+
"""Get global database manager instance."""
79+
global _db_manager
80+
if _db_manager is None:
81+
_db_manager = DatabaseManager()
82+
return _db_manager
83+
84+
85+
def get_db() -> Generator[Session, None, None]:
86+
"""Get database session for FastAPI dependency injection."""
87+
db_manager = get_database_manager()
88+
yield from db_manager.get_db_session()
89+
90+
91+
def get_engine() -> Engine:
92+
"""Get database engine."""
93+
return get_database_manager().get_engine()
94+
95+
96+
def create_tables() -> None:
97+
"""Create all database tables."""
98+
get_database_manager().create_tables()
99+
100+
101+
def drop_tables() -> None:
102+
"""Drop all database tables."""
103+
get_database_manager().drop_tables()

0 commit comments

Comments
 (0)