This commit is contained in:
2026-01-12 11:33:43 +08:00
commit f07062dbd7
38 changed files with 6805 additions and 0 deletions

399
CODE_ARCHITECTURE.md Normal file
View File

@@ -0,0 +1,399 @@
# 青岛岗位匹配系统 - 代码架构文档
## 项目概述
这是一个基于 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`)
**职责**:应用启动、依赖注入、路由配置、优雅关闭
**核心流程**
1. 加载配置文件(支持 `-config` 参数指定路径)
2. 初始化各类客户端LLM、高德、岗位、OCR
3. 初始化服务层(位置、岗位、政策、聊天)
4. 配置 Gin 路由和中间件
5. 启动 HTTP 服务器
6. 监听系统信号,实现优雅关闭
**路由配置**
| 路径 | 方法 | 说明 |
|------|------|------|
| `/` | GET | API 信息 |
| `/health` | GET | 健康检查 |
| `/metrics` | GET | 性能指标 |
| `/v1/chat/completions` | POST | 聊天接口(主接口) |
| `/debug/pprof/*` | GET | 性能分析 |
---
### 2. 配置模块 (`internal/config/`)
**文件**`config.go`
**职责**:配置加载、环境变量覆盖、默认值设置
**配置结构**
```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_MODEL`
- `AMAP_API_KEY`
- `OCR_BASE_URL`
- `POLICY_LOGIN_NAME` / `POLICY_USER_KEY` / `POLICY_SERVICE_ID`
- `SERVER_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 支持
- 超时配置
- 缓冲区优化
```go
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` - 核心聊天服务
**职责**:消息处理、工具调用编排、流式输出
**核心方法**
```go
ProcessChatRequest(req) // 非流式处理
ProcessChatRequestStream(ctx, req) // 流式处理
```
**关键特性**
1. **岗位意图检测** (`isJobQueryIntent`)
- 关键词匹配检测用户是否在查询岗位
- 检测到岗位意图时强制调用工具
2. **幻觉检测** (`containsJobHallucination`)
- 正则匹配检测 AI 是否自行编造岗位信息
- 拦截幻觉输出,强制重新调用工具
3. **简历检测** (`isResumeContent`)
- 关键词匹配判断 OCR 内容是否为简历
- 非简历内容会提示先询问用户意图
4. **工具调用循环**
- 最多 10 轮工具调用
- 自动合并流式响应中的分块工具调用
- 岗位结果分块输出(每个岗位间隔 1 秒)
5. **消息预处理** (`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 能力实现智能工具调用:
1. 用户发送消息
2. LLM 分析意图,决定调用哪些工具
3. 服务端执行工具调用,获取真实数据
4. 将工具结果返回给 LLM
5. LLM 基于真实数据生成回复
### 2. 幻觉防护
为防止 LLM 编造岗位信息:
1. **意图检测**:检测到岗位查询时设置 `tool_choice=required`
2. **输出检测**:正则匹配检测疑似编造的岗位信息
3. **强制重试**:检测到幻觉时强制重新调用工具
### 3. 流式输出优化
- 岗位信息分块输出,每个岗位间隔 1 秒
- 使用 `job-json` 代码块格式,便于前端渲染
- 过滤 tool_calls 相关 chunk对客户端透明
### 4. 连接池优化
- LLM 客户端200 最大连接100/host
- 其他客户端100 最大连接50/host
- 启用 HTTP/2
- 32KB 读写缓冲
---
## 扩展指南
### 添加新工具
1.`model/tool.go``GetAvailableTools()` 中添加工具定义
2.`service/chat_service.go``executeToolCall()` 中添加处理分支
3. 实现对应的处理函数
### 添加新的外部服务
1.`config/config.go` 中添加配置结构
2.`client/` 下创建新的客户端
3.`service/` 下创建对应的服务层
4.`main.go` 中初始化并注入