一、组件概述
Prompt 组件是一个功能强大的提示词模板引擎,专门设计用于简化与大语言模型(LLM)的交互过程。它通过模板化管理,实现了对话消息的动态生成、标准化组装和复用,显著提升了开发效率。
核心价值
动态变量替换:支持多种模板语法,实现灵活的变量填充
消息结构化:规范化系统指令、用户输入和模型输出的格式
模板复用:一次定义,多次使用,确保提示词一致性
二、模板引擎详解
1. FString 格式 (schema.FString)
特点:简单直观的字符串插值,适合基础替换场景
语法规则:
使用
{变量名}格式进行占位支持嵌套对象访问:
{user.name}自动类型转换和空值处理
适用场景:
简单的文本替换需求
不需要复杂逻辑的静态模板
性能要求较高的场景
// 示例模板
template := prompt.FromMessages(schema.FString,
schema.SystemMessage("你是一个{role}专家,擅长{domain}领域"),
schema.UserMessage("请帮我{task},具体要求:{requirement}"),
)
2. GoTemplate 格式 (schema.GoTemplate)
特点:基于 Go 标准库的强大模板引擎,支持复杂逻辑
语法特性:
条件判断:
{{if .condition}}...{{end}}循环遍历:
{{range .items}}...{{end}}函数调用:
{{.value | upper}}管道操作:
{{.data | json | indent}}
适用场景:
需要条件逻辑的复杂模板
数据结构遍历需求
需要自定义函数的场景
// 示例模板
template := prompt.FromMessages(schema.GoTemplate,
schema.SystemMessage(`{{if .expert}}作为{{.expert}}专家,{{end}}请用{{.tone}}的语气回答`),
schema.UserMessage(`问题:{{.question}}{{if .context}}
相关背景:{{.context}}{{end}}`),
)
3. Jinja2 格式 (schema.Jinja2)
特点:兼容流行的 Jinja2 语法,适合 Python 背景的开发者
语法特性:
条件语句:
{% if condition %}...{% endif %}循环控制:
{% for item in items %}...{% endfor %}过滤器:
{{ variable | filter }}模板继承:支持宏和包含
适用场景:
从 Python 项目迁移的场景
需要复杂模板逻辑的项目
团队熟悉 Jinja2 语法的情况
// 示例模板
template := prompt.FromMessages(schema.Jinja2,
schema.SystemMessage("你是一个{{role}}{% if level %} {{level}}级{% endif %}专家"),
schema.UserMessage("问题:{{question}}{% if examples %}
示例:{{examples}}{% endif %}"),
)
三、完整使用示例
环境配置
package main
import (
"context"
"log"
"os"
"time"
"github.com/cloudwego/eino-ext/components/model/openai"
"github.com/cloudwego/eino/components/model"
"github.com/cloudwego/eino/components/prompt"
"github.com/cloudwego/eino/schema"
)
// 配置常量
const (
DOUBAO_MODEL_NAME = "doubao-seed-1-6-251015"
DOUBAO_BASE_URL = "https://ark.cn-beijing.volces.com/api/v3"
)
1. 创建聊天模型
func createOpenAIChatModel(ctx context.Context) model.ToolCallingChatModel {
key := os.Getenv("DOUBAO_API_KEY")
if key == "" {
log.Fatal("DOUBAO_API_KEY environment variable is required")
}
chatModel, err := openai.NewChatModel(ctx, &openai.ChatModelConfig{
BaseURL: DOUBAO_BASE_URL,
Model: DOUBAO_MODEL_NAME,
APIKey: key,
})
if err != nil {
log.Fatalf("创建OpenAI聊天模型失败: %v", err)
}
return chatModel
}
2. 模板创建与使用
// 创建FString模板(推荐用于简单场景)
func createFstringTemplate() prompt.ChatTemplate {
return prompt.FromMessages(schema.FString,
schema.SystemMessage("你是一位{role},请用{tone}的语气回答用户问题。"),
schema.UserMessage("问题:{question}"),
// 可添加助理消息模板用于多轮对话
)
}
// 创建GoTemplate模板(推荐用于复杂逻辑)
func createGoTemplate() prompt.ChatTemplate {
return prompt.FromMessages(schema.GoTemplate,
schema.SystemMessage(`你是一位{{.role}}专家。
{{if .level -}}
你是{{.level}}级别的专家。
{{end -}}
请用{{.tone}}的语气回答问题。`),
schema.UserMessage(`问题:{{.question}}
{{if .context -}}
背景信息:{{.context}}
{{end -}}
{{if .examples -}}
参考示例:{{.examples}}
{{end}}`),
)
}
// 创建Jinja2模板
func createJinja2Template() prompt.ChatTemplate {
return prompt.FromMessages(schema.Jinja2,
schema.SystemMessage(`你是一位{{role}}专家{% if specialty %},擅长{{specialty}}{% endif %}。
请用{{tone}}的语气回答问题。`),
schema.UserMessage(`问题:{{question}}
{% if constraints %}
约束条件:
{% for constraint in constraints %}
- {{constraint}}
{% endfor %}
{% endif %}`),
)
}
3. 消息生成与格式化
func createMessagesFromTemplate(templateType string) []*schema.Message {
var template prompt.ChatTemplate
// 根据类型选择模板引擎
switch templateType {
case "fstring":
template = createFstringTemplate()
case "go":
template = createGoTemplate()
case "jinja2":
template = createJinja2Template()
default:
template = createFstringTemplate() // 默认使用FString
}
// 模板变量数据
variables := map[string]any{
"role": "资深技术专家",
"tone": "专业且友好",
"question": "如何系统性地优化大型数据库的性能?",
"level": "高级",
"context": "系统用户量超过100万,数据表有50+",
"examples": "包括索引优化、查询重构、硬件升级等方案",
"specialty": "数据库优化",
"constraints": []string{"约束条件1", "约束条件2"},
}
// 格式化生成消息
messages, err := template.Format(context.Background(), variables)
if err != nil {
log.Fatalf("模板格式化失败: %v", err)
}
log.Printf("生成的消息数量: %d", len(messages))
for i, msg := range messages {
log.Printf("消息%d: 角色=%s, 内容=%s", i+1, msg.Role, msg.Content)
}
return messages
}
4. 模型调用封装
// 普通生成模式
func generateContent(ctx context.Context, llm model.ToolCallingChatModel, messages []*schema.Message) *schema.Message {
result, err := llm.Generate(ctx, messages)
if err != nil {
log.Fatalf("LLM生成失败: %v", err)
}
log.Printf("生成完成 - Token使用: 输入=%d, 输出=%d",
result.ResponseMeta.Usage.PromptTokens,
result.ResponseMeta.Usage.CompletionTokens)
return result
}
// 流式生成模式
func streamContent(ctx context.Context, llm model.ToolCallingChatModel, messages []*schema.Message) {
stream, err := llm.Stream(ctx, messages)
if err != nil {
log.Fatalf("流式生成失败: %v", err)
}
defer stream.Close()
log.Println("开始流式生成...")
var fullResponse string
for {
chunk, err := stream.Recv()
if err != nil {
break // 流结束
}
if chunk.Content != "" {
print(chunk.Content)
fullResponse += chunk.Content
}
}
println() // 换行
log.Printf("流式生成完成,总字符数: %d", len(fullResponse))
}
5. 主函数与错误处理
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
defer cancel()
// 1. 创建聊天模型
log.Println("=== 初始化聊天模型 ===")
chatModel := createOpenAIChatModel(ctx)
// 2. 选择模板类型并生成消息
log.Println("=== 生成对话消息 ===")
messages := createMessagesFromTemplate("fstring") // 可改为 "go" 或 "jinja2"
// 3. 选择生成模式
log.Println("=== 开始内容生成 ===")
// 模式选择:普通生成 或 流式生成
generationMode := "stream" // 可改为 "normal"
switch generationMode {
case "normal":
log.Println("使用普通生成模式...")
result := generateContent(ctx, chatModel, messages)
log.Printf("最终结果: %s", result.Content)
case "stream":
log.Println("使用流式生成模式...")
streamContent(ctx, chatModel, messages)
default:
log.Println("使用默认的流式生成模式...")
streamContent(ctx, chatModel, messages)
}
log.Println("=== 程序执行完成 ===")
}