后端: 1.新建conv/schedule_persist.go:ScheduleState Diff 持久化,事务内逐变更写库,支持 place/move/unplace 三种操作(当前 event source) 2.新建conv/schedule_provider.go:ScheduleState 加载适配,从 DB 合并 existing events + pending task items 3.新建dao/agent_state_store_adapter.go:Redis 状态快照存取适配,实现 AgentStateStore 接口 4.新建service/agentsvc/agent_newagent.go:newAgent service 集成层,串联 LLM 客户端、ScheduleProvider、SchedulePersistor 和 ChunkEmitter 5.更新node/execute.go:接入 SchedulePersistor(写操作确认后持久化)、完善 confirm resume 路径(PendingConfirmTool 恢复分支)、correction 机制增加连续失败计数上限 6.更新api/agent.go + cmd/start.go:接入 newAgent service,完成 API 层路由注册 7.新建node/execute_confirm_flow_test.go + llm_tool_orchestration_test.go:确认回路 7 个测试 + 端到端排课 5 个测试全部通过 8.新建newAgent/ARCHITECTURE.md + ROADMAP.md:全链路架构文档和缺口分析 9.代码审查整理:提取 prompt/base.go(通用 buildStageMessages 等5个辅助)、tools/args.go(参数解析辅助);write_tools 尾部辅助移入 write_helpers;修复 queryRangeSpecific sb.Reset() 逻辑缺陷和 Unplace guest Duration 未恢复;ScheduleStateProvider/SchedulePersistor 归入 state_store.go;emitter 内部 Build*Text 函数降级为私有 前端:无 仓库:无
94 lines
2.9 KiB
Go
94 lines
2.9 KiB
Go
// 过渡期遗留文件。
|
||
//
|
||
// 这里的 CallArkText / CallArkJSON 是为了让旧 agent 代码(route/quicknote 等)
|
||
// 在迁移到统一 Client 之前能继续直接持有 *ark.ChatModel。
|
||
//
|
||
// 替代路径:
|
||
// - CallArkText → WrapArkClient(arkModel) + client.GenerateText(...)
|
||
// - CallArkJSON → WrapArkClient(arkModel) + GenerateJSON[T](...)
|
||
//
|
||
// 待旧 agent 代码全部收敛到 Client 接口后,本文件可整体删除。
|
||
package newagentllm
|
||
|
||
import (
|
||
"context"
|
||
"errors"
|
||
"strings"
|
||
|
||
"github.com/cloudwego/eino-ext/components/model/ark"
|
||
einoModel "github.com/cloudwego/eino/components/model"
|
||
"github.com/cloudwego/eino/schema"
|
||
arkModel "github.com/volcengine/volcengine-go-sdk/service/arkruntime/model"
|
||
)
|
||
|
||
// ArkCallOptions 是基于 ark.ChatModel 的通用调用选项。
|
||
//
|
||
// 设计目的:
|
||
// 1. 当前 route / quicknote 都还直接持有 *ark.ChatModel;
|
||
// 2. 在它们完全收敛到更抽象的 Client 前,先把重复的 ark 调用样板抽成公共层;
|
||
// 3. 这样本轮就能先删除 route/quicknote 里那几份重复的 Generate 样板代码。
|
||
type ArkCallOptions struct {
|
||
Temperature float64
|
||
MaxTokens int
|
||
Thinking ThinkingMode
|
||
}
|
||
|
||
// CallArkText 调用 ark 模型并返回纯文本。
|
||
//
|
||
// 职责边界:
|
||
// 1. 负责拼 system + user 两段消息;
|
||
// 2. 负责统一配置 thinking / temperature / maxTokens;
|
||
// 3. 负责拦截空响应;
|
||
// 4. 不负责 JSON 解析,不负责业务字段校验。
|
||
func CallArkText(ctx context.Context, chatModel *ark.ChatModel, systemPrompt, userPrompt string, options ArkCallOptions) (string, error) {
|
||
if chatModel == nil {
|
||
return "", errors.New("ark model is nil")
|
||
}
|
||
|
||
messages := []*schema.Message{
|
||
schema.SystemMessage(systemPrompt),
|
||
schema.UserMessage(userPrompt),
|
||
}
|
||
resp, err := chatModel.Generate(ctx, messages, buildArkOptions(options)...)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
if resp == nil {
|
||
return "", errors.New("模型返回为空")
|
||
}
|
||
|
||
text := strings.TrimSpace(resp.Content)
|
||
if text == "" {
|
||
return "", errors.New("模型返回内容为空")
|
||
}
|
||
return text, nil
|
||
}
|
||
|
||
// CallArkJSON 调用 ark 模型并直接解析 JSON。
|
||
func CallArkJSON[T any](ctx context.Context, chatModel *ark.ChatModel, systemPrompt, userPrompt string, options ArkCallOptions) (*T, string, error) {
|
||
raw, err := CallArkText(ctx, chatModel, systemPrompt, userPrompt, options)
|
||
if err != nil {
|
||
return nil, "", err
|
||
}
|
||
parsed, err := ParseJSONObject[T](raw)
|
||
if err != nil {
|
||
return nil, raw, err
|
||
}
|
||
return parsed, raw, nil
|
||
}
|
||
|
||
func buildArkOptions(options ArkCallOptions) []einoModel.Option {
|
||
thinkingType := arkModel.ThinkingTypeDisabled
|
||
if options.Thinking == ThinkingModeEnabled {
|
||
thinkingType = arkModel.ThinkingTypeEnabled
|
||
}
|
||
opts := []einoModel.Option{
|
||
ark.WithThinking(&arkModel.Thinking{Type: thinkingType}),
|
||
einoModel.WithTemperature(float32(options.Temperature)),
|
||
}
|
||
if options.MaxTokens > 0 {
|
||
opts = append(opts, einoModel.WithMaxTokens(options.MaxTokens))
|
||
}
|
||
return opts
|
||
}
|