# AI 服务统一说明 **更新时间**: 2025-12-27 --- ## 统一后的 AI 服务架构 系统已完成 AI 服务的统一整理,现在只保留一个标准的 AI 服务实现。 --- ## 文件位置 ### ✅ 保留的文件(唯一 AI 服务实现) **核心服务:** - **`api/services/ai_service.js`** - AI 服务主文件(基于阿里云 Qwen 2.5) - **`api/services/ai_call_recorder.js`** - AI 调用记录服务 **导出管理:** - **`api/services/index.js`** - 服务统一导出 **数据库层:** - **`api/model/ai_call_records.js`** - AI 调用记录模型 **后台管理:** - **`api/controller_admin/ai_call_records.js`** - 后台管理 API **前端界面:** - **`admin/src/views/system/ai_call_records.vue`** - 管理界面 - **`admin/src/api/system/ai_call_records_server.js`** - API 服务 ### ❌ 已删除的文件 - ~~`api/middleware/job/aiService.js`~~ - 已删除(内容已迁移到 `services/ai_service.js`) --- ## 使用方式 ### 1. 直接引用(推荐) ```javascript const aiService = require('./services/ai_service'); // 使用 AI 服务 const result = await aiService.analyzeJob(jobInfo, resumeInfo); ``` ### 2. 通过服务管理器 ```javascript const { AIService } = require('./services'); // 使用 AI 服务 const result = await AIService.analyzeJob(jobInfo, resumeInfo); ``` --- ## AI 服务功能列表 ### 核心方法 | 方法 | 说明 | 业务类型 | |------|------|---------| | `callAPI(prompt, options)` | 基础 API 调用 | 自定义 | | `analyzeJob(jobInfo, resumeInfo)` | 岗位智能筛选 | `job_analysis` | | `generateChatContent(jobInfo, resumeInfo, chatType)` | 生成个性化聊天 | `chat_generation` | | `analyzeResume(resumeText)` | 简历分析 | `resume_analysis` | | `generateInterviewInvitation(jobInfo, chatHistory)` | 生成面试邀约 | `interview_invitation` | | `identifyOutsourcingJob(jobInfo)` | 识别外包岗位 | `outsourcing_detection` | ### 辅助方法 | 方法 | 说明 | |------|------| | `recordAiCall(params)` | 记录 AI 调用 | | `calculateCost(totalTokens)` | 计算调用费用 | --- ## Token 自动记录 所有通过 `callAPI()` 方法的调用都会自动记录以下信息: - **Token 使用量**:prompt_tokens, completion_tokens, total_tokens - **成本信息**:基于模型计算的费用 - **性能指标**:响应时间(毫秒) - **状态跟踪**:成功/失败状态 - **业务关联**:business_type, reference_id - **请求追踪**:完整的请求和响应内容 记录过程是异步非阻塞的,不会影响 AI 调用的主流程。 --- ## 配置说明 ### 环境变量 在 `.env` 文件中配置: ```bash # 阿里云 DashScope API Key AI_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxx # 模型选择(可选) AI_MODEL=qwen-turbo # qwen-turbo, qwen-plus, qwen-max, qwen-long ``` ### 代码配置 ```javascript // 在 config/config.js 中 module.exports = { ai: { apiKey: process.env.AI_API_KEY, model: process.env.AI_MODEL || 'qwen-turbo' } } ``` --- ## 模型选择 | 模型 | 速度 | 质量 | 成本 | 价格(元/1000 tokens)| |------|------|------|------|---------------------| | qwen-turbo | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ¥0.003 | | qwen-plus | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ¥0.004 | | qwen-max | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ¥0.12 | | qwen-long | ⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ | - | --- ## 使用示例 ### 示例 1:岗位分析 ```javascript const aiService = require('./services/ai_service'); const jobInfo = { companyName: '阿里巴巴', jobTitle: 'Node.js 高级工程师', salary: '30-50K', location: '杭州', description: '负责后端服务开发...', skills: 'Node.js, MySQL, Redis' }; const resumeInfo = { skills: 'Node.js, JavaScript, MySQL', experience: '5年后端开发经验', education: '本科', expectedSalary: '35K' }; const result = await aiService.analyzeJob(jobInfo, resumeInfo); console.log(result.analysis); ``` ### 示例 2:生成聊天内容 ```javascript const result = await aiService.generateChatContent( jobInfo, resumeInfo, 'greeting' // greeting, interview, followup ); console.log(result.content); ``` ### 示例 3:简历分析 ```javascript const resumeText = ` 姓名:张三 技能:Node.js, React, MySQL 工作经验:3年全栈开发 ... `; const result = await aiService.analyzeResume(resumeText); console.log(result.analysis); // { // skillTags: ['Node.js', 'React', 'MySQL'], // strengths: '...', // weaknesses: '...', // careerSuggestion: '...', // competitiveness: 75 // } ``` ### 示例 4:自定义 AI 调用 ```javascript const result = await aiService.callAPI( '请帮我分析这个岗位的发展前景...', { systemPrompt: '你是一个职业规划专家...', temperature: 0.7, maxTokens: 2000, user_id: 123, business_type: 'career_analysis' } ); console.log(result.content); ``` --- ## 错误处理 AI 服务内置了重试机制(最多 3 次)和错误处理: ```javascript try { const result = await aiService.analyzeJob(jobInfo, resumeInfo); } catch (error) { console.error('AI 调用失败:', error.message); // 错误会自动记录到 ai_call_records 表 } ``` --- ## 监控与统计 ### 查看调用记录 登录后台管理系统:**系统设置** → **AI调用记录** ### 统计信息 - 总调用次数 - Token 总使用量 - 总费用统计 - 平均响应时间 - 成功率 ### 编程方式获取统计 ```javascript const AiCallRecorder = require('./services/ai_call_recorder'); // 获取用户统计 const userStats = await AiCallRecorder.getUserTokenStats(userId, { startDate: new Date('2025-01-01'), endDate: new Date('2025-12-31') }); console.log(userStats); // { // total_calls: 100, // total_prompt_tokens: 5000, // total_completion_tokens: 3000, // total_tokens: 8000, // total_cost: 24.00, // avg_response_time: 1500 // } ``` --- ## 注意事项 ### 1. API Key 安全 - ❌ 不要将 API Key 硬编码在代码中 - ❌ 不要将 `.env` 文件提交到版本控制 - ✅ 使用环境变量管理 API Key - ✅ 生产环境使用独立的 API Key ### 2. 成本控制 - 选择合适的模型(开发用 turbo,生产用 plus) - 设置合理的 `maxTokens` 限制 - 监控 Token 使用量 - 定期查看费用统计 ### 3. 性能优化 - 重试机制已内置(3 次) - 超时设置为 30 秒 - Token 记录是异步的,不阻塞主流程 ### 4. 数据隐私 - 请求和响应内容会完整记录到数据库 - 注意敏感信息的处理 - 定期清理历史记录 --- ## 迁移指南 如果你的代码之前引用了 `middleware/job/aiService.js`,请修改为: ```javascript // ❌ 旧代码 const aiService = require('../middleware/job/aiService'); // ✅ 新代码 const aiService = require('../services/ai_service'); ``` 功能保持完全一致,只是路径发生了变化。 --- ## 故障排查 ### 问题 1:模型未加载 **错误信息:** `Cannot read property 'findAll' of undefined` **解决方法:** 1. 确认已执行建表 SQL:`_sql/create_ai_call_records_table.sql` 2. 重启 Node.js 服务 3. 检查 `api/model/ai_call_records.js` 是否存在 ### 问题 2:认证失败 **错误信息:** `auth header format should be Bearer sk-...` **解决方法:** 1. 检查 `.env` 文件中的 `AI_API_KEY` 2. 确认 API Key 格式正确(以 `sk-` 开头) 3. 验证 API Key 有效性 ### 问题 3:记录失败 **警告信息:** `记录AI调用失败(不影响主流程)` **解决方法:** 1. 检查数据库连接 2. 确认 `ai_call_records` 表存在 3. 查看详细错误日志 ### 问题 4:费用计算不准确 **解决方法:** 1. 检查 `calculateCost()` 方法中的价格配置 2. 根据实际使用的模型调整价格 3. 定期对账单进行核对 --- ## 相关文档 - [AI 服务配置说明](ai_service_config.md) - 详细的环境配置指南 - [功能实施总结](implementation_summary.md) - 完整的功能实施文档 - [API 文档](../api/controller_admin/ai_call_records.js) - 后台 API 接口说明 --- **文档版本**: 1.0 **最后更新**: 2025-12-27 **维护者**: 开发团队