Appearance
Go 后端架构
分层职责
Handler(参数校验 / 响应封装 / 额度检查)
↓
Service(业务逻辑 / 事务协调)
↓
Repository(数据访问 / SQL 构建)
↓
Model(GORM 模型定义)配置管理
文件:internal/config/config.go + config.yaml
- Viper 加载 YAML + 环境变量覆盖
- 结构体:
Server,Database,Redis,JWT,AIConfig,Qdrant,SubscriptionConfig,LangfuseConfig SubscriptionConfig:FreeDailyLimit,FreeFollowUpMaxTokens,PaidFollowUpMaxTokens,AllowMockPurchaseAIConfig:DefaultProvider,DefaultModel,APIKey,Agents(per-agentAgentModelConfig)- Langfuse 密钥支持环境变量覆盖(
LANGFUSE_PUBLIC_KEY等) CONFIG_PATH指定配置文件路径
中间件链
gin.Recovery → CORS → [路由分组]
├── /auth (公开: register / login / refresh)
└── /authed → JWTAuth → LoadSubscriptionContext → [子路由]
├── /auth (profile / self-profile)
├── /subscription
├── /persons
├── /chat
└── /strategy- JWTAuth:解析 Bearer token → 写
user_id到 Context - LoadSubscriptionContext:加载订阅信息到 Context(
subscription_unlimited等) - CORS:开发阶段允许所有来源
用量与额度(Handler 内,非全局中间件):
- 每日「首问」:Redis
INCR+EXPIRE,Keyratelimit:{userID}:{YYYY-MM-DD} - 追问:同一会话或
strategyThreadId线程内计数;免费 ≤3、付费 ≤10 - 策略线程历史存 Redis list(
strategyhistory:{userID}:{threadID}),支持多轮上下文
数据模型
| 模型 | 文件 | 要点 |
|---|---|---|
| User | model/user.go | SelfProfile(JSON)、SubscriptionTier、bcrypt 密码 |
| Person | model/person.go | PersonalityTags(StringSlice/JSON)、ImportanceLevel 1-5 |
| ChatSession / ChatMessage | model/chat.go | 一对多;PersonIDs(JSON);按 created_at ASC 排序 |
| EmotionSnapshot | model/emotion.go | UserMood / OtherMood / Trend / Tags(JSON);关联 Session + Person |
| Interaction / Strategy / Subscription | 各自文件 | 已定义,部分功能待产品化 |
Repository 层
- PersonRepository:CRUD + 模糊搜索 + relationship_type 过滤 + 分页
- UserRepository:FindByEmail / FindByID / Create / Update
Service 层
- AuthService:Register / Login / RefreshToken / UpdateProfile / GetSelfProfile / UpdateSelfProfile
- PersonService:透传 Repository + 用户 ID 隔离
与 Agent 子系统的边界
- 传统 CRUD / 认证:
AuthHandler、PersonHandler、SubscriptionHandler只依赖 Service → Repository,不引用internal/agent。 - AI 能力:
ChatHandler、StrategyHandler持有*agent.System,在 Handler 内完成额度与上下文加载后,调用Chat/Analyze/Advise/Script。 - 混合:
ImportHandler→ImportService仅使用agent.System的 默认 LLM(DefaultModel())做结构化抽取,不经过多 Agent Runner。
数据契约:HTTP JSON ↔ AgentContext / StreamChunk 的字段约定见 api_routes.md「HTTP 层与 Agent 层如何对接」与 sse.md。
Handler 层
统一响应格式:
go
type Response struct {
Code int `json:"code"`
Message string `json:"message"`
Data interface{} `json:"data,omitempty"`
}- Auth Handler:Register / Login / RefreshToken / GetProfile / UpdateProfile / GetSelfProfile / UpdateSelfProfile
- Chat Handler:SendMessage / StreamMessage / ListSessions / GetSession / DeleteSession;额度检查 + 近期互动摘要注入 + 情绪追踪
- 资料提案门控与抽取:根据「我的画像 / 关联人脉是否偏空」等规则决定是否在本轮流式结束后附加
profileProposal(见internal/handler/profile_extract_gate.go、internal/agent/profile_extract.go)。Agent 侧工具可将提案写入会话级 pending,或由 Handler 在结束前调用ExtractProfileProposal。DB 仅在用户于前端确认后通过既有 Profile API 更新。
- 资料提案门控与抽取:根据「我的画像 / 关联人脉是否偏空」等规则决定是否在本轮流式结束后附加
- Strategy Handler:Analyze / Advise / Script;
strategyThreadId+ Redis 线程历史加载 + 额度 - Subscription Handler:Usage / MockActivate
数据库初始化
AutoMigrate (pkg/database/mysql.go):启动时迁移所有 GORM 模型(含 EmotionSnapshot)。 连接池:MaxIdleConns=10, MaxOpenConns=100。生产环境建议 golang-migrate。