#大模型##大模型框架##大模型开发#
完整内容同步发布于公众号:AI开发的后端厨师,CSDN:巴塞罗那的风
官方文档:ChatTemplate 指南
今天我们来聊聊 Eino 框架中的 ChatTemplate 组件。如果你正在构建 AI 应用,Prompt 工程必定是绕不开的话题,而 ChatTemplate 就是 Eino 框架帮你管理 Prompt 的利器。
ChatTemplate 到底是什么?
简单来说,ChatTemplate 就是一个智能的 Prompt 模板引擎。官方给的定义是这样的:
type ChatTemplate interface {
Format(ctx context.Context, vs map[string]any, opts ...Option) ([]*schema.Message, error)
}
翻译成人话:它能把带占位符的模板和具体的变量值结合起来,生成模型能理解的标准消息格式。
想象一下,你不需要每次都写完整的 Prompt,而是像这样:
- 模板:”你是一个{role},请帮我{task}。”
- 变量:{“role”: “专业的助手”, “task”: “写一首诗”}
- 结果:”你是一个专业的助手,请帮我写一首诗。”
这就是 ChatTemplate 干的事情!
动手实践:如何创建你的第一个 Prompt 模板?
先看看官方示例是怎么做的:
// 1. 创建模板 - 就像准备一个填空题
template := prompt.FromMessages(schema.FString,
schema.SystemMessage("你是一个{role}。"),
schema.MessagesPlaceholder("history_key", false),
&schema.Message{
Role: schema.User,
Content: "请帮我{task}。",
},
)
// 2. 准备要填的"答案"
variables := map[string]any{
"role": "专业的助手",
"task": "写一首诗",
"history_key": []*schema.Message{
{Role: schema.User, Content: "告知我油画是什么?"},
{Role: schema.Assistant, Content: "油画是xxx"},
},
}
// 3. 填空,生成完整的消息
messages, err := template.Format(context.Background(), variables)
在实际应用中有什么区别?
你可能会问:单独使用和在 Eino 编排框架中使用,有什么不同?
主要有两点区别:
- 变量来源不同
- 单独使用:变量一般是自己手动写的
- 编排中使用:变量可能来自前序节点(列如获取用户历史、画像等信息)
- 调用方式不同
- 单独使用:需要自己调用 Format() 方法
- 编排中使用:框架会自动帮你调用
但无论哪种方式,核心都是同一个 Format 函数。所以,理解这个函数是关键!
深入源码:ChatTemplate 是如何工作的?
让我们揭开 Format 函数的神秘面纱:
func (t *DefaultChatTemplate) Format(ctx context.Context,
vs map[string]any, _ ...Option) (result []*schema.Message, err error) {
// 第一步:触发回调函数(框架的监控和追踪机制)
ctx = callbacks.EnsureRunInfo(ctx, t.GetType(), components.ComponentOfPrompt)
ctx = callbacks.OnStart(ctx, &CallbackInput{
Variables: vs,
Templates: t.templates,
})
// 第二步:真正的"填空"工作
result = make([]*schema.Message, 0, len(t.templates))
for _, template := range t.templates {
msgs, err := template.Format(ctx, vs, t.formatType) // 这里调用每个子模板的Format
if err != nil {
return nil, err
}
result = append(result, msgs...) // 把结果拼起来
}
// 第三步:结束回调
_ = callbacks.OnEnd(ctx, &CallbackOutput{
Result: result,
Templates: t.templates,
})
return result, nil
}
可以看到,
DefaultChatTemplate.Format 主要做两件事:
- 管理回调(框架的内部机制)
- 调用各个子模板的 Format 方法,然后合并结果
模板的多种格式:不只是简单的字符串替换
说到这里,你可能会好奇:那个 t.formatType 是什么?实则这就是 Eino 支持的不同模板格式:

从上图可以看到,Eino 支持多种格式化方式。红框里的五种本质上是类似的,都是字符串模板的变体。而红框外的 MessagesPlaceholder 则更简单直接:
// MessagesPlaceholder 的实现很简单:
// 直接从变量map里取出对应的消息列表
msgList, ok := vs[key].([]*schema.Message)
这种设计特别适合追加历史消息的场景。列如你把对话历史存在 history_key 中,ChatTemplate 就能自动把它插入到 Prompt 的合适位置,给模型提供完整的上下文。
设计思想:为什么需要 ChatTemplate?
你可能会想:我自己拼接字符串不也行吗?为什么需要这么个组件?
ChatTemplate 的设计解决了几个实际问题:
- 复用性:同样的模板结构,换上不同的变量就能用于不同场景
- 可维护性:Prompt 模板聚焦管理,修改起来方便
- 灵活性:支持动态插入历史对话、系统指令等
- 标准化:确保生成的消息格式符合模型要求
最佳实践提议
根据官方文档的使用经验,这里有一些提议:
- 模板设计要模块化
// 好的设计:模块清晰
template := prompt.FromMessages(schema.FString,
schema.SystemMessage("你是一个{role},{style}"),
schema.MessagesPlaceholder("history", false),
schema.UserMessage("{user_query}"),
)
- 变量命名要有意义
- 使用 user_query 而不是 q
- 使用 conversation_history 而不是 hist
- 合理使用消息占位符
- 对于固定内容:用字符串模板 {variable}AIaiAI
- 对于动态消息列表:用 MessagesPlaceholder
总结
ChatTemplate 是 Eino 框架中一个看似简单但超级实用的组件。它把 Prompt 工程中的模板管理问题抽象成了一个清晰的接口,让开发者能更专注于 Prompt 内容本身,而不是字符串拼接的细节。
无论你是想快速原型验证,还是构建复杂的生产系统,ChatTemplate 都能帮你更优雅地管理 Prompt。下次当你发现自己在重复拼接字符串构建 Prompt 时,不妨试试 ChatTemplate!
膜拜大佬👏