71f0a1abdb
- 所有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>
139 lines
4.7 KiB
Go
139 lines
4.7 KiB
Go
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 持有 LLMClient,Provider 需要能访问它。
|
||
// 这里我们返回一个"占位"结果——实际 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
|