修复架构和代码规范违规问题: 架构修复: - 创建internal目录(内部模块,禁止外部import) - 恢复ARCHITECTURE.md文档 - 移除未定义的utils目录 - 清理临时测试目录 代码规范修复(严格遵循核心哲学): - 移除所有try-except,让错误立即暴露 - 移除所有防护编程(不返回bool/错误字符串) - 简化为MVP版本(每个命令组只保留核心功能) - 移除所有美化输出,使用简单print 功能实现: - 实现generate命令(只保留task子命令) - 实现assemble命令(只保留tables子命令) - 修复bidmaster/__init__.py导出 - 添加缺失的TableGenerator类 文件精简: - generate.py: 262行 → 66行 - assemble.py: 293行 → 64行 - 移除所有延迟导入和内部import 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
338 lines
8.2 KiB
Markdown
338 lines
8.2 KiB
Markdown
# BidMaster-CLI 项目规范文档
|
||
|
||
## 一、项目概述
|
||
|
||
BidMaster-CLI 是一个AI标书撰写助手项目,通过智能化标书制作流程提升投标效率和中标率。项目采用Python语言开发,遵循"核心需求第一、立即失败、MVP至上"的开发哲学。
|
||
|
||
## 二、架构设计规范
|
||
|
||
### 2.1 分层架构(禁止逆向引用)
|
||
|
||
```
|
||
┌─────────────────────────────────────┐
|
||
│ CLI Layer (Interface) │ ← 命令行接口
|
||
├─────────────────────────────────────┤
|
||
│ Agent Layer (Orchestration) │ ← 业务编排
|
||
├─────────────────────────────────────┤
|
||
│ Tools Layer (Infrastructure) │ ← 基础设施
|
||
└─────────────────────────────────────┘
|
||
```
|
||
|
||
### 2.2 目录结构规范(≤8文件规则)
|
||
|
||
```
|
||
bidmaster-cli/
|
||
├── src/
|
||
│ └── bidmaster/
|
||
│ ├── internal/ # 内部模块,禁止外部import
|
||
│ ├── cli/ # 仅暴露命令接口(≤8文件)
|
||
│ ├── agents/ # Agent逻辑(≤8文件)
|
||
│ ├── tools/ # 原子工具(≤8文件)
|
||
│ ├── models/ # 数据模型
|
||
│ ├── config/ # 配置中心
|
||
│ └── __init__.py # 统一导出接口
|
||
├── templates/ # Word模板
|
||
├── config/ # 配置文件
|
||
├── data/ # 数据存储
|
||
└── main.py # 唯一入口
|
||
```
|
||
|
||
### 2.3 Python语言映射表
|
||
|
||
| 通用概念 | Python实现 | BidMaster应用场景 |
|
||
|---------|-----------|------------------|
|
||
| 共用组件 | `__init__.py` + `__all__` | tools模块统一导出 |
|
||
| 配置主题 | `pydantic.BaseSettings` | config/settings.py |
|
||
| HTTP拦截 | `httpx.Auth` 自定义Transport | OpenAI客户端封装 |
|
||
| 生命周期 | `contextlib.ExitStack` | 数据库连接管理 |
|
||
| 错误边界 | 自定义Exception → ErrorCode | BidMasterError体系 |
|
||
| 依赖注入 | `fastapi.Depends` / 手动注入 | Agent依赖注入 |
|
||
| 插件链 | 装饰器 + `functools.wraps` | 工具函数增强 |
|
||
|
||
## 三、核心开发原则
|
||
|
||
### 3.1 核心哲学实施
|
||
|
||
```python
|
||
# 1. 核心需求第一 - 不做防护编程
|
||
def parse_document(file_path: Path) -> dict:
|
||
# 直接处理,不做备份
|
||
with open(file_path, 'rb') as f:
|
||
return extract_content(f) # 失败就失败
|
||
|
||
# 2. 立即失败 - 错误必须暴露
|
||
if not api_key:
|
||
raise ValueError("API_KEY未配置") # 不提供默认值
|
||
|
||
# 3. MVP至上 - 只实现必要功能
|
||
class WordProcessor:
|
||
def fill_template(self, data: dict):
|
||
# 只填充,不校验格式、不美化样式
|
||
pass
|
||
```
|
||
|
||
### 3.2 统一配置管理
|
||
|
||
```python
|
||
# config/settings.py - 唯一配置源
|
||
from pydantic_settings import BaseSettings
|
||
|
||
class Settings(BaseSettings):
|
||
# 三层配置:默认值 → 配置文件 → 环境变量
|
||
model_name: str = "gpt-4"
|
||
api_key: str # 必须从环境变量读取
|
||
chunk_size: int = 1000
|
||
|
||
class Config:
|
||
env_file = ".env"
|
||
env_prefix = "BIDMASTER_"
|
||
|
||
# 单例模式
|
||
settings = Settings()
|
||
```
|
||
|
||
### 3.3 错误处理规范
|
||
|
||
```python
|
||
# models/exceptions.py
|
||
class BidMasterError(Exception):
|
||
"""基础异常类"""
|
||
def __init__(self, code: str, message: str):
|
||
self.code = code # 错误码
|
||
self.message = message
|
||
super().__init__(f"[{code}] {message}")
|
||
|
||
# 使用示例
|
||
class ParserError(BidMasterError):
|
||
"""解析错误"""
|
||
pass
|
||
|
||
# 立即抛出,不吞没
|
||
if not file_path.exists():
|
||
raise ParserError("FILE_NOT_FOUND", f"文件不存在: {file_path}")
|
||
```
|
||
|
||
## 四、代码质量保证
|
||
|
||
### 4.1 门禁工具链(强制执行)
|
||
|
||
```yaml
|
||
# .pre-commit-config.yaml
|
||
repos:
|
||
- repo: https://github.com/psf/black
|
||
hooks:
|
||
- id: black
|
||
args: [--line-length=88]
|
||
|
||
- repo: https://github.com/charliermarsh/ruff-pre-commit
|
||
hooks:
|
||
- id: ruff
|
||
args: [--select, "E,F,I,N,UP", --fix]
|
||
|
||
- repo: https://github.com/pre-commit/mirrors-mypy
|
||
hooks:
|
||
- id: mypy
|
||
args: [--strict]
|
||
```
|
||
|
||
### 4.2 命名与类型规范
|
||
|
||
```python
|
||
# 类名:PascalCase
|
||
class DocumentParser:
|
||
pass
|
||
|
||
# 函数/变量:snake_case
|
||
def generate_content(task_id: str) -> dict[str, Any]:
|
||
result_data: dict = {}
|
||
return result_data
|
||
|
||
# 常量:UPPER_CASE(放在文件头部)
|
||
MAX_TOKENS = 4000
|
||
DEFAULT_TEMPERATURE = 0.7
|
||
|
||
# 私有成员:单下划线前缀
|
||
def _internal_helper() -> None:
|
||
pass
|
||
|
||
# 类型注解:100%覆盖
|
||
from typing import Optional, TypedDict
|
||
|
||
class TaskResult(TypedDict):
|
||
content: str
|
||
confidence: float
|
||
metadata: dict[str, Any]
|
||
```
|
||
|
||
## 五、工作流程规范
|
||
|
||
### 5.1 开发流程(6步法)
|
||
|
||
```bash
|
||
# 1. 从模板初始化(5分钟启动)
|
||
cookiecutter templates/module-template/
|
||
|
||
# 2. 实现核心功能(MVP)
|
||
# tools/new_tool.py
|
||
def core_function(input: dict) -> dict:
|
||
# 最简实现,不做优化
|
||
pass
|
||
|
||
# 3. 添加类型注解
|
||
def core_function(input: dict[str, str]) -> dict[str, Any]:
|
||
pass
|
||
|
||
# 4. 编写测试
|
||
# tests/test_new_tool.py
|
||
def test_core_function():
|
||
result = core_function({"key": "value"})
|
||
assert result is not None
|
||
|
||
# 5. 运行门禁
|
||
pre-commit run --all-files
|
||
|
||
# 6. 集成到CLI
|
||
# cli/commands.py
|
||
@click.command()
|
||
def new_command():
|
||
"""新功能入口"""
|
||
pass
|
||
```
|
||
|
||
### 5.2 Agent开发规范
|
||
|
||
```python
|
||
# agents/new_agent.py
|
||
from typing import Any
|
||
from pydantic import BaseModel
|
||
|
||
class AgentInput(BaseModel):
|
||
"""输入模型"""
|
||
task: str
|
||
context: dict[str, Any]
|
||
|
||
class NewAgent:
|
||
"""单一职责Agent"""
|
||
|
||
def __init__(self, tools: list):
|
||
self.tools = tools # 依赖注入
|
||
|
||
async def run(self, input: AgentInput) -> dict:
|
||
"""执行逻辑"""
|
||
# 1. 解析输入
|
||
# 2. 调用工具
|
||
# 3. 返回结果
|
||
return {"status": "completed"}
|
||
```
|
||
|
||
### 5.3 工具开发规范
|
||
|
||
```python
|
||
# tools/new_tool.py
|
||
from pathlib import Path
|
||
from typing import Optional
|
||
|
||
def process_file(
|
||
file_path: Path,
|
||
*, # 强制关键字参数
|
||
encoding: str = "utf-8",
|
||
timeout: Optional[int] = None
|
||
) -> dict[str, Any]:
|
||
"""处理文件
|
||
|
||
Args:
|
||
file_path: 文件路径
|
||
encoding: 编码格式
|
||
timeout: 超时时间(秒)
|
||
|
||
Returns:
|
||
处理结果字典
|
||
|
||
Raises:
|
||
FileNotFoundError: 文件不存在
|
||
ValueError: 参数无效
|
||
"""
|
||
if not file_path.exists():
|
||
raise FileNotFoundError(f"文件不存在: {file_path}")
|
||
|
||
# 核心逻辑
|
||
with open(file_path, encoding=encoding) as f:
|
||
content = f.read()
|
||
|
||
return {"content": content, "size": len(content)}
|
||
```
|
||
|
||
## 六、最小可执行骨架
|
||
|
||
```python
|
||
# main.py - 唯一入口
|
||
from bidmaster.config import settings
|
||
from bidmaster.cli import create_app
|
||
|
||
def main():
|
||
"""启动入口"""
|
||
# 1. 加载配置
|
||
settings.validate()
|
||
|
||
# 2. 初始化依赖
|
||
# 3. 启动CLI
|
||
app = create_app()
|
||
app()
|
||
|
||
if __name__ == "__main__":
|
||
main()
|
||
|
||
# bidmaster/__init__.py - 统一导出
|
||
__all__ = ["parse", "generate", "assemble"]
|
||
|
||
from .tools.parser import parse
|
||
from .tools.rag import generate
|
||
from .tools.table import assemble
|
||
|
||
# bidmaster/config/settings.py - 配置中心
|
||
from pydantic_settings import BaseSettings
|
||
|
||
class Settings(BaseSettings):
|
||
model_name: str = "gpt-4"
|
||
api_key: str
|
||
|
||
class Config:
|
||
env_file = ".env"
|
||
env_prefix = "BIDMASTER_"
|
||
|
||
settings = Settings()
|
||
```
|
||
|
||
## 七、性能与监控
|
||
|
||
### 7.1 性能指标
|
||
|
||
- 项目初始化:< 3分钟
|
||
- 单章节生成:< 60秒
|
||
- 内存占用:< 2GB
|
||
- 向量检索:< 500ms
|
||
|
||
### 7.2 日志规范
|
||
|
||
```python
|
||
import logging
|
||
from datetime import datetime
|
||
|
||
# 统一日志格式
|
||
logging.basicConfig(
|
||
level=logging.INFO,
|
||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
||
)
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
# 性能日志
|
||
start = datetime.now()
|
||
result = process()
|
||
logger.info(f"处理完成,耗时: {(datetime.now() - start).seconds}秒")
|
||
```
|
||
|
||
|
||
---
|
||
|
||
**一句话总结:让90%的场景只有一条官方路径,代码直接明了,错误立即暴露,功能MVP即止。** |