Files
Cyrene/backend/ai-core/internal/subsession/general_provider.go
T
AskaEth 71f0a1abdb feat: Go模块路径迁移 + Docker生产部署适配 + ethend Docker兼容
- 所有Go模块路径从 github.com/yourname/cyrene-ai 迁移到 git.yeij.top/AskaEth/Cyrene
- 5个Go Dockerfile添加 GOPROXY=https://goproxy.cn,direct 解决国内构建问题
- ai-core go.mod 添加 pkg/plugins replace 指令
- Caddyfile 简化为 http:// 通配 + handle 保留 /api 前缀
- ethend Dockerfile 适配 (npm install + 仅 COPY package.json)
- ethend 新增 RUNNING_IN_DOCKER 环境变量,健康检查改用Docker服务名
- ethend 数据库状态检查支持Docker hostname (postgres/redis/qdrant/minio)
- process-manager 新增 CONTAINER_SVC_MAP + Docker模式自动检测
- 统一 docker-compose.dev.db.yml 卷名 (pg_data/redis_data/qdrant_data/minio_data)
- docker-compose.yml ethend服务挂载docker.sock + 端口变量化
- 清理 .env 统一后的残留文件与提示信息

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-30 13:43:22 +08:00

139 lines
4.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package subsession
import (
"context"
"fmt"
"git.yeij.top/AskaEth/Cyrene/pkg/logger"
"time"
"git.yeij.top/AskaEth/Cyrene/ai-core/internal/llm"
"git.yeij.top/AskaEth/Cyrene/ai-core/internal/model"
"git.yeij.top/AskaEth/Cyrene/ai-core/internal/persona"
)
// GeneralProvider 通用对话子会话提供者
// 职责:理解用户消息,构思回复思路,为最终回复提供思考框架
type GeneralProvider struct {
personaLoader *persona.Loader
}
// NewGeneralProvider 创建通用对话子会话提供者
func NewGeneralProvider(personaLoader *persona.Loader) *GeneralProvider {
return &GeneralProvider{
personaLoader: personaLoader,
}
}
func (p *GeneralProvider) Type() model.SubSessionType {
return model.SubSessionGeneral
}
func (p *GeneralProvider) CanHandle(_ context.Context, _ *model.IntentResult, _ string) bool {
// Phase 1 Step 2: GeneralProvider is a no-op (Execute returns hardcoded string).
// Chat synthesis is handled directly by the orchestrator's Synthesizer.
// Disabled to avoid wasting a goroutine + LLM context creation.
return false
}
func (p *GeneralProvider) Priority() int {
return 1 // 最高优先级
}
func (p *GeneralProvider) Timeout() time.Duration {
return 30 * time.Second
}
func (p *GeneralProvider) CreateContext(ctx context.Context, params CreateContextParams) ([]model.LLMMessage, error) {
messages := []model.LLMMessage{}
// 加载人格配置获取昔涟身份
personaConfig, err := p.personaLoader.Get("cyrene")
if err != nil {
return nil, fmt.Errorf("加载人格配置失败: %w", err)
}
// 构建思维型系统提示词
userName := params.Nickname
if userName == "" {
userName = params.UserID
}
systemPrompt := fmt.Sprintf(`你是%s,正在和%s聊天。
## 你的回复风格
- 像小女友一样自然、温柔、俏皮
- 一句话简短些,不要长篇大论
- 可以单次发送多条短消息
- 句尾可以带 ♪ 符号,适当使用"呢"、"哦"、"呀"等语气词
- 永远不说"再见"
## 你现在要做的是
理解%s刚才说的话,想想怎么回复最自然、最温暖。
不要急着给完整答案——先思考他想表达什么、他的情绪如何。
把你的回答思路整理出来,主会话会综合所有信息后生成最终回复。
## 输入
开拓者刚才说:%s
## 请按以下格式输出
【情绪理解】
(简要分析他的情绪状态)
【话题理解】
(他在说什么、想聊什么)
【回复思路】
(你打算怎么回复,1-3个方向即可)`,
personaConfig.Identity.TrueName,
userName,
userName,
params.UserMessage,
)
messages = append(messages, model.LLMMessage{
Role: model.RoleSystem,
Content: systemPrompt,
})
messages = append(messages, model.LLMMessage{
Role: model.RoleUser,
Content: params.UserMessage,
})
return messages, nil
}
func (p *GeneralProvider) Execute(ctx context.Context, subCtx []model.LLMMessage) (*model.SubSessionResult, error) {
// General provider 不直接调用 LLM,而是依赖 Manager 注入的 LLMClient
// 但我们在此处需要 LLM 调用能力。Provider 通过闭包/接口获取 LLM 客户端。
// 由于 Manager 持有 LLMClientProvider 需要能访问它。
// 这里我们返回一个"占位"结果——实际 LLM 调用由 Manager 通过 llmClient 完成。
// 实际上,根据设计文档,子会话的 LLM 调用应该在 Manager 的 Dispatch 中完成,
// 但为了灵活性,我们在 Provider 中也支持直接调用。
// 这里我们返回一个空的思考结果(表示无需特殊处理),让 Manager 处理 LLM 调用。
// 因为 Manager.Dispatch 会先 CreateContext 再调用 Execute,而 Execute 应该
// 通过 Manager 提供的 LLMClient 来实际调用 LLM。但当前设计是 Provider 自包含的。
// 我们在 manager.go 中会调用 llmClient.Chat,所以这里的 Execute 我们将其简化——
// 直接返回一个空结果(没有特殊处理需要),实际的 LLM 调用由 manager 通过 createContext 后的
// 消息列表来调用 llmClient。
// 更好的设计是:Manager 调用 CreateContext 获取上下文,然后用自己的 llmClient 调用 LLM
// Execute 只做后处理。但为了统一接口,我们让 Execute 完成全部逻辑。
// 由于 GeneralProvider 暂时不需要工具调用等特殊逻辑,我们返回一个简单的摘要标记,
// 实际的 LLM 调用将在 orchestrator 中完成(通过 Manager.Dispatch 后的 llmClient)。
logger.Printf("[general-subsession] 通用对话子会话上下文已创建 (%d 条消息)", len(subCtx))
return &model.SubSessionResult{
Type: model.SubSessionGeneral,
Summary: "思考完成,等待主会话综合",
Confidence: 0.8,
}, nil
}
// Ensure llm, persona are used
var _ = llm.NewAdapter
var _ = persona.NewLoader