12 KiB
12 KiB
青岛岗位匹配系统 - 代码架构文档
项目概述
这是一个基于 Go 语言开发的智能岗位匹配系统,提供兼容 OpenAI /v1/chat/completions API 的接口。系统集成了 LLM 大模型、高德地图、OCR 文件解析、政策咨询等多种服务。
目录结构
qd-sc/
├── cmd/server/main.go # 应用入口
├── internal/ # 内部包(不对外暴露)
│ ├── api/ # API 层
│ │ ├── handler/ # HTTP 请求处理器
│ │ └── middleware/ # 中间件
│ ├── client/ # 外部服务客户端
│ ├── config/ # 配置管理
│ ├── model/ # 数据模型定义
│ └── service/ # 业务逻辑层
├── pkg/ # 公共包(可对外暴露)
│ ├── metrics/ # 性能指标收集
│ └── utils/ # 工具函数
└── config.yaml # 配置文件
模块详解
1. 入口模块 (cmd/server/main.go)
职责:应用启动、依赖注入、路由配置、优雅关闭
核心流程:
- 加载配置文件(支持
-config参数指定路径) - 初始化各类客户端(LLM、高德、岗位、OCR)
- 初始化服务层(位置、岗位、政策、聊天)
- 配置 Gin 路由和中间件
- 启动 HTTP 服务器
- 监听系统信号,实现优雅关闭
路由配置:
| 路径 | 方法 | 说明 |
|---|---|---|
/ |
GET | API 信息 |
/health |
GET | 健康检查 |
/metrics |
GET | 性能指标 |
/v1/chat/completions |
POST | 聊天接口(主接口) |
/debug/pprof/* |
GET | 性能分析 |
2. 配置模块 (internal/config/)
文件:config.go
职责:配置加载、环境变量覆盖、默认值设置
配置结构:
type Config struct {
Server ServerConfig // 服务器配置(端口、超时)
LLM LLMConfig // LLM 配置(API地址、密钥、模型)
Amap AmapConfig // 高德地图配置
JobAPI JobAPIConfig // 岗位 API 配置
OCR OCRConfig // OCR 服务配置
Policy PolicyConfig // 政策咨询配置
Logging LoggingConfig // 日志配置
Performance PerformanceConfig // 性能配置
}
环境变量支持:
LLM_API_KEY/LLM_BASE_URL/LLM_MODELAMAP_API_KEYOCR_BASE_URLPOLICY_LOGIN_NAME/POLICY_USER_KEY/POLICY_SERVICE_IDSERVER_PORT
3. 数据模型 (internal/model/)
3.1 openai.go - OpenAI 兼容模型
定义与 OpenAI API 兼容的请求/响应结构:
ChatCompletionRequest- 聊天请求ChatCompletionResponse- 聊天响应ChatCompletionChunk- 流式响应块Message- 消息结构(支持文本和多模态)Tool/ToolCall- 工具调用相关ErrorResponse- 错误响应
3.2 job.go - 岗位相关模型
JobQueryRequest- 岗位查询请求参数JobAPIResponse- 岗位 API 原始响应JobListing- 单个岗位信息FormattedJob- 格式化后的岗位信息EducationMap/ExperienceMap/LocationMap- 代码映射表
3.3 policy.go - 政策咨询模型
PolicyTicketRequest/Response- Ticket 获取PolicyChatRequest/Response- 政策对话
3.4 tool.go - 工具定义
GetAvailableTools() - 返回所有可用工具:
| 工具名 | 功能 |
|---|---|
queryLocation |
查询地点经纬度(高德地图) |
queryJobsByArea |
按区域代码查询岗位 |
queryJobsByLocation |
按经纬度查询附近岗位 |
parsePDF |
解析 PDF 文件 |
parseImage |
解析图片文件 |
queryPolicy |
政策咨询 |
SystemPrompt - 系统提示词,定义 AI 助手的行为规范:
- 强制调用工具获取岗位数据,禁止编造
- 工具链思维模式
- 输出格式要求
4. 客户端层 (internal/client/)
4.1 http_client.go - HTTP 客户端工厂
提供优化的 HTTP 客户端配置:
- 连接池管理
- HTTP/2 支持
- 超时配置
- 缓冲区优化
NewHTTPClient(config) // 通用客户端
NewLLMHTTPClient(timeout) // LLM 专用(更大连接池)
4.2 llm_client.go - LLM 客户端
方法:
ChatCompletion()- 非流式请求(带重试机制)ChatCompletionStream()- 流式请求(返回 channel)
特性:
- 自动重试(5xx 和 429 错误)
- SSE 流式解析
- 大缓冲区防止超大响应
4.3 amap_client.go - 高德地图客户端
方法:
SearchPlace(keywords)- 搜索地点GetLocationCoordinates(keywords)- 获取经纬度
4.4 job_client.go - 岗位 API 客户端
方法:
QueryJobs(req)- 查询岗位列表FormatJobResponse(apiResp)- 格式化响应(代码转文字)
4.5 ocr_client.go - OCR 服务客户端
方法:
ParseURL(fileURL)- 解析远程文件(图片/PDF/Excel/PPT)
4.6 policy_client.go - 政策咨询客户端
方法:
GetTicket()- 获取访问票据(自动缓存,1小时有效)Chat(chatReq)- 非流式对话ChatStream(chatReq)- 流式对话
5. 服务层 (internal/service/)
5.1 chat_service.go - 核心聊天服务
职责:消息处理、工具调用编排、流式输出
核心方法:
ProcessChatRequest(req) // 非流式处理
ProcessChatRequestStream(ctx, req) // 流式处理
关键特性:
-
岗位意图检测 (
isJobQueryIntent)- 关键词匹配检测用户是否在查询岗位
- 检测到岗位意图时强制调用工具
-
幻觉检测 (
containsJobHallucination)- 正则匹配检测 AI 是否自行编造岗位信息
- 拦截幻觉输出,强制重新调用工具
-
简历检测 (
isResumeContent)- 关键词匹配判断 OCR 内容是否为简历
- 非简历内容会提示先询问用户意图
-
工具调用循环
- 最多 10 轮工具调用
- 自动合并流式响应中的分块工具调用
- 岗位结果分块输出(每个岗位间隔 1 秒)
-
消息预处理 (
prepareMessages)- 注入系统提示词
- 处理 Vision API 格式的文件 URL
- 自动调用 OCR 解析文件
5.2 job_service.go - 岗位服务
方法:
QueryJobsByArea(params)- 按区域查询QueryJobsByLocation(params)- 按位置查询
5.3 location_service.go - 位置服务
方法:
QueryLocation(keywords)- 查询地点坐标
5.4 policy_service.go - 政策服务
方法:
QueryPolicy(...)- 政策咨询(支持多轮对话和实名咨询)
6. API 处理器 (internal/api/handler/)
6.1 chat.go - 聊天处理器
方法:
ChatCompletions(c)- 主接口处理- 验证请求参数
- 根据
stream参数分发到流式/非流式处理
流式响应:
- SSE 格式输出
- 支持客户端断开检测
- 错误时发送错误 chunk
6.2 health.go - 健康检查
返回服务状态信息。
6.3 metrics.go - 指标处理器
返回性能统计数据。
6.4 response.go - 统一响应
提供 Error() 和 Success() 方法统一响应格式。
7. 中间件 (internal/api/middleware/)
7.1 cors.go - 跨域处理
- 支持携带凭证的请求
- 预检请求处理
- 24 小时缓存
7.2 ratelimit.go - 限流
算法:令牌桶(Token Bucket)
配置:
- 桶容量:200(最大突发)
- 补充速率:50/秒(持续 QPS)
实现:CAS 无锁算法,高并发友好
7.3 recovery.go - Panic 恢复
捕获 panic,打印堆栈,返回 500 错误。
7.4 metrics.go - 指标收集
记录请求数、延迟、失败数等指标。
8. 工具包 (pkg/)
8.1 metrics/metrics.go - 性能指标
收集指标:
- 请求计数(总数、活跃、失败、流式)
- 延迟统计(平均、最小、最大)
- 系统指标(goroutine、内存、GC)
实现:原子操作 + sync.Map,无锁高性能
8.2 utils/json.go - JSON 工具
ToJSONStringPretty() - 格式化 JSON 输出
数据流图
用户请求
│
▼
┌─────────────────┐
│ Gin Router │
│ + 中间件 │
│ (CORS/限流/恢复)│
└────────┬────────┘
│
▼
┌─────────────────┐
│ ChatHandler │
│ (请求验证) │
└────────┬────────┘
│
▼
┌─────────────────┐
│ ChatService │◄──────────────────────┐
│ (核心编排) │ │
└────────┬────────┘ │
│ │
┌────┴────┬────────┬────────┐ │
▼ ▼ ▼ ▼ │
┌───────┐ ┌───────┐ ┌───────┐ ┌───────┐ │
│LLM │ │Job │ │Location│ │Policy │ │
│Client │ │Service│ │Service │ │Service│ │
└───┬───┘ └───┬───┘ └───┬───┘ └───┬───┘ │
│ │ │ │ │
▼ ▼ ▼ ▼ │
┌───────┐ ┌───────┐ ┌───────┐ ┌───────┐ │
│OpenAI │ │岗位API │ │高德API │ │政策API │ │
│ API │ │ │ │ │ │ │ │
└───────┘ └───────┘ └───────┘ └───────┘ │
│ │
└─────────────────────────────────────┘
(工具调用循环)
关键设计
1. 工具调用机制
系统通过 LLM 的 Function Calling 能力实现智能工具调用:
- 用户发送消息
- LLM 分析意图,决定调用哪些工具
- 服务端执行工具调用,获取真实数据
- 将工具结果返回给 LLM
- LLM 基于真实数据生成回复
2. 幻觉防护
为防止 LLM 编造岗位信息:
- 意图检测:检测到岗位查询时设置
tool_choice=required - 输出检测:正则匹配检测疑似编造的岗位信息
- 强制重试:检测到幻觉时强制重新调用工具
3. 流式输出优化
- 岗位信息分块输出,每个岗位间隔 1 秒
- 使用
job-json代码块格式,便于前端渲染 - 过滤 tool_calls 相关 chunk,对客户端透明
4. 连接池优化
- LLM 客户端:200 最大连接,100/host
- 其他客户端:100 最大连接,50/host
- 启用 HTTP/2
- 32KB 读写缓冲
扩展指南
添加新工具
- 在
model/tool.go的GetAvailableTools()中添加工具定义 - 在
service/chat_service.go的executeToolCall()中添加处理分支 - 实现对应的处理函数
添加新的外部服务
- 在
config/config.go中添加配置结构 - 在
client/下创建新的客户端 - 在
service/下创建对应的服务层 - 在
main.go中初始化并注入