apply-helper / docs /spec.md
hanbinChen's picture
Refactor LLM service and analysis logic for improved structure and error handling
6c8af71
# 📑 技术规格说明(SPR) — AI-powered Resume & Cover Letter Generator
## 1. 项目结构
```
apply-helper/
├── pyproject.toml # 项目依赖与配置
├── uv.lock # UV 依赖锁定文件
├── .env.example # 环境变量配置模板
├── src/ # 源代码根目录
│ ├── streamlit_app.py # Streamlit 前端主入口
│ ├── mock_data.py # 测试用模拟数据
│ ├── services/ # 业务逻辑层
│ │ ├── __init__.py
│ │ ├── analyse_service.py # JD/用户信息分析与总结
│ │ ├── generation_service.py # 简历与求职信生成
│ │ └── llm_service.py # LLM/LiteLLM 统一封装与调用
│ └── llm/ # LLM集成层
│ ├── __init__.py
│ ├── litellm_client.py # LiteLLM API 封装
│ └── prompt_templates.py # LLM Prompt 模板管理
├── docs/ # 文档目录
│ ├── prd.md # 产品需求文档
│ ├── spec.md # 技术规格说明(本文件)
│ ├── services.spec.md # 服务层规格说明
│ └── llm.spec.md # LLM集成规格说明
└── tests/ # 单元测试(待实现)
```
## 2. 主要 Python 文件与函数
### 2.1 `src/streamlit_app.py` — Streamlit 前端主入口
- **页面布局**: 侧边栏输入控制,主区域双列预览(简历 + 求职信)
- **会话状态管理**: 使用 `st.session_state` 持久化分析结果、生成文档和错误状态
- **主要函数**
- `main()`:应用入口,负责页面配置、UI渲染与交互逻辑
- `initialize_session_state()`:初始化会话状态变量
- `handle_analyse(jd: str, user_info: str)`:分析按钮回调,包含输入验证、调用服务、异常处理
- `handle_refine(feedback: str)`:优化按钮回调,基于反馈更新分析
- `handle_mock_analyse()`:模拟分析按钮回调,加载预设测试数据
- **模拟数据功能**: 三个按钮支持加载模拟JD、简历和完整分析结果
- **错误处理**: 集中化错误显示,用户友好提示信息
### 2.2 LLM 集成层
#### `src/services/llm_service.py` — LLM服务包装层
- **核心功能**: 提供LLM调用的统一接口,负责提示词模板格式化和LiteLLM调用
- **主要函数**:
- `analyse_llm(jd: str, user_info: str) -> str`: 工作分析,返回原始LLM响应字符串
- `refine_llm(summary_json: str, feedback: str) -> str`: 基于反馈优化分析,返回原始LLM响应
- `generate_resume_llm(summary_json: str, user_info: str) -> str`: 生成Markdown格式简历
- `generate_cover_letter_llm(job_description: str, user_info: str) -> str`: 生成德语求职信
#### `src/llm/litellm_client.py` — LiteLLM客户端集成
- **多Provider支持**: 优先支持Azure OpenAI,备用支持标准OpenAI
- **自动配置**: 基于环境变量自动检测和配置最优客户端
- **主要函数**:
- `call_llm(prompt: str, model: str = None, max_tokens: int = 800, temperature: float = 1.0) -> str`
- `get_azure_client() -> dict`: 配置Azure OpenAI客户端
- `get_openai_client() -> dict`: 配置标准OpenAI客户端
- 包含连接测试和调试模式,支持litellm debug
#### `src/llm/prompt_templates.py` — 提示词模板管理
- **模板类型**: analyse, refine, generate_resume, generate_cover_letter
- **函数**: `get_template(name: str) -> str`
- **特点**:
- 字典存储,包含详细的JSON输出格式要求
- ANALYSE_PROMPT: 德国科技市场专家角色,8-12个技能提取,4-6个匹配点分析
- GENERATE_COVER_LETTER_PROMPT: 德语商务求职信生成,符合德国商务信函规范
- 所有模板包含明确的输出格式要求和角色设定
#### 核心处理逻辑
- **提示词管理**: 从模板获取提示词,使用Python字符串format动态替换参数
- **LLM调用**: 通过LiteLLM统一接口调用不同provider的模型
- **错误处理**: LiteLLM层处理API调用异常,服务层处理业务逻辑异常
- **响应处理**: 返回原始字符串响应,由上层服务负责结构化解析
### 2.3 业务服务层
#### `src/services/analyse_service.py` — 分析服务
- **功能**: 职位描述与用户背景的匹配分析,使用Pydantic数据模型
- **数据模型**: `AnalysisResult(BaseModel)` - 结构化分析结果
- key_skills: List[str] - 关键技能列表
- match_points: List[str] - 匹配优势点
- gap_points: List[str] - 技能差距点
- suggestions: List[str] - 改进建议
- pitch: str - 价值主张
- **主要逻辑**:
- 验证输入参数非空
- 委托LLM服务进行分析
- `_parse_analysis_response()` - 复杂JSON解析逻辑,处理代码块包装
- `analyse()` - 初始分析,返回AnalysisResult对象
- `refine()` - 基于反馈优化分析,使用model_dump_json()序列化
#### `src/services/generation_service.py` — 文档生成服务
- **功能**: 编排简历和求职信的生成
- **主要接口**:
- `generate_resume(summary: AnalysisResult, user_info: str) -> str` - 生成简历
- `generate_cover_letter(job_description: str, user_info: str) -> str` - 生成求职信
- `generate_both(summary: AnalysisResult, user_info: str, job_description: str) -> Tuple[str, str]` - 生成完整文档对
- **主要逻辑**:
- 使用AnalysisResult对象和原始文本作为输入
- 调用LLM服务生成简历(Markdown)和求职信(德语文本)
- 支持动态导入处理,兼容模块和独立运行
- 返回生成的文档元组
### 2.4 模拟数据系统
#### `src/mock_data.py` — 测试数据管理
- **MOCK_JD**: 完整的高级软件工程师职位描述
- **MOCK_RESUME**: John Smith 的详细简历信息
- **Analysis_Summary**: 结构化分析结果(Dict格式)
- key_skills, match_points, gap_points, suggestions, pitch
- **Resume**: 生成的Markdown格式简历
- **Cover_Letter**: 生成的纯文本求职信
- **用途**: 支持无需LLM调用的完整工作流测试
## 3. Streamlit UI 实现
### 3.1 页面布局
- **侧边栏(Sidebar)**:
- **模拟数据按钮**: 三列布局 - "Load Mock JD", "Load Mock Resume", "Mock Analyse"
- **输入区域**:
- Job Description 文本区域(高度150px)
- User Resume/Info 文本区域(高度200px)
- **控制按钮**: "Analyse" 按钮(全宽)
- **优化区域**:
- Feedback 文本区域(高度100px)
- "Refine" 按钮(全宽)
- **主区域(Main Area)**:
- **错误显示**: 使用 `st.error()` 显示异常信息
- **分析摘要**: 使用 `st.json()` 展示结构化分析结果
- **双列预览**:
- 左列: Resume 预览(Markdown 渲染)
- 右列: Cover Letter 预览(纯文本显示)
### 3.2 会话状态管理
**状态变量**:
- `summary` - 分析摘要结果
- `resume_md` - 生成的简历Markdown
- `cover_letter_txt` - 生成的求职信文本
- `error` - 错误信息显示
- `user_info_input` - 用户输入缓存
### 3.3 交互流程
1. **标准工作流**:
- 输入JD和用户信息 → 点击"Analyse" → 显示分析和生成结果
- 输入反馈 → 点击"Refine" → 更新分析和重新生成
2. **模拟数据工作流**:
- 点击"Load Mock JD" → 自动填充职位描述
- 点击"Load Mock Resume" → 自动填充简历信息
- 点击"Mock Analyse" → 直接加载完整分析结果
3. **错误处理**:
- 输入验证: 检查空值,显示友好错误信息
- 异常捕获: 包装在try-catch中,显示具体错误消息
- 状态清理: 成功时清除error状态
## 4. 技术实现详情
### 4.1 依赖管理
**核心依赖**: streamlit (UI), litellm (LLM调用), python-dotenv (环境变量), weasyprint (PDF,未使用), pydantic (验证,未使用)
**安装和运行**:
1. `pip install uv` - 安装包管理器
2. `uv sync` - 同步依赖
3. `cp .env.example .env` - 配置环境变量
4. `uv run streamlit run src/streamlit_app.py` - 启动应用
### 4.2 LLM集成配置
**多Provider支持**: 优先Azure OpenAI,备用标准OpenAI
**Azure OpenAI配置**: AZURE_OPENAI_API_KEY, AZURE_OPENAI_ENDPOINT, AZURE_OPENAI_MODEL, AZURE_OPENAI_API_VERSION(默认2024-12-01-preview)
**OpenAI配置**: OPENAI_API_KEY(使用gpt-3.5-turbo模型)
**配置逻辑**:
- 优先检测Azure配置,如果完整则使用Azure
- Azure不可用时回退到标准OpenAI
- 支持模型参数覆盖,但仅支持azure/前缀的模型
- 包含详细的配置验证和错误提示
### 4.3 开发和测试
**模拟数据测试**:
- 无需配置LLM即可测试完整UI流程
- `src/mock_data.py` 包含完整测试数据集
- 点击"Mock Analyse"按钮即可加载预设结果
**调试和测试模式**:
- `python src/llm/litellm_client.py` - 测试LLM连接和配置验证
- `python src/services/analyse_service.py` - 测试分析服务完整流程
- `python src/services/generation_service.py` - 测试文档生成流程
- 包含litellm._turn_on_debug()调试支持
### 4.4 架构特点
**模块化设计**:
- 业务逻辑与UI分离
- LLM集成层独立封装
- 服务层薄包装,便于替换实现
**扩展点**:
- 添加新的LLM provider: 扩展 `litellm_client.py` 中的客户端配置函数
- 添加PDF导出: 实现 `pdf_service.py` 集成WeasyPrint
- 添加新的生成模板: 在 `prompt_templates.py` 中添加新模板常量
- 数据验证增强: 当前使用Pydantic AnalysisResult模型,可扩展更多验证模型
- 多语言支持: 扩展prompt_templates支持不同语言的求职信生成