ChatTemplate

视频讲解地址:点击直达open in new window

1. 模版化方式

ChatTemplate 支持多种模板化方式,最常见的包括:

  1. FString 格式:使用 {variable} 语法进行变量替换
  2. GoTemplate 格式:使用 Go 标准库的 text/template 语法,支持条件判断、循环等复杂逻辑
  3. Jinja2 格式:使用 Jinja2 模板语法

2. FString

代码:

func main() {
	//这里先使用ollama的方式实现
	ctx := context.Background()
	model, err := ollama.NewChatModel(ctx, &ollama.ChatModelConfig{
		BaseURL: "http://127.0.0.1:11434",
		Model:   "modelscope.cn/Qwen/Qwen3-32B-GGUF:latest",
	})
	if err != nil {
		panic(err)
	}
	//创建message,这个就相当于给大模型的提示词,分为系统输入和用户输入
	//系统输入就是预设的提示词,用户输入就是用户输入的内容
	//message := []*schema.Message{
	//	schema.SystemMessage("你是一个乐于助人的助手"),
	//	schema.UserMessage("请介绍一下Go语言的特点"),
	//}
	template := prompt.FromMessages(
		schema.FString,
		schema.SystemMessage("你是一个{role}, 请用{tone}的语气回答问题"),
		schema.UserMessage("{question}"),
	)
	vars := map[string]any{
		"role":     "技术专家",
		"tone":     "专业严谨",
		"question": "如何优化数据库性能",
	}
	message, err := template.Format(ctx, vars)
	//获取流式回复
	stream, err := model.Stream(ctx, message)
	if err != nil {
		panic(err)
	}
	defer stream.Close()

	for {
		chunk, err := stream.Recv()
		if err != nil {
			break
		}
		print(chunk.Content)
	}
	//换行
	println()
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

3. GoTemplate

代码:

func main() {
	//这里先使用ollama的方式实现
	ctx := context.Background()
	model, err := ollama.NewChatModel(ctx, &ollama.ChatModelConfig{
		BaseURL: "http://127.0.0.1:11434",
		Model:   "modelscope.cn/Qwen/Qwen3-32B-GGUF:latest",
	})
	if err != nil {
		panic(err)
	}
	//创建message,这个就相当于给大模型的提示词,分为系统输入和用户输入
	//系统输入就是预设的提示词,用户输入就是用户输入的内容
	//message := []*schema.Message{
	//	schema.SystemMessage("你是一个乐于助人的助手"),
	//	schema.UserMessage("请介绍一下Go语言的特点"),
	//}
	template := prompt.FromMessages(
		schema.GoTemplate,
		schema.SystemMessage("{{if .isExpert}}你是一个专家级{{.domain}}顾问。{{else}}你是一个初级{{.domain}}助手。{{end}}\n{{if .isFormal}}请使用正式的语言风格。{{else}}请使用友好的语言风格。{{end}}\n你的任务是{{.task}}。"),
		schema.UserMessage("{{.question}}"),
	)
	//vars := map[string]any{
	//	"isExpert": true,
	//	"domain":   "数据库",
	//	"isFormal": true,
	//	"task":     "提供专业的数据库优化建议",
	//	"question": "如何优化大型数据库的查询性能?",
	//}
	vars := map[string]interface{}{
		"isExpert": false,
		"domain":   "编程",
		"isFormal": false,
		"task":     "帮助初学者理解编程概念",
		"question": "什么是变量?",
	}
	message, err := template.Format(ctx, vars)
	for _, v := range message {
		println(v.Content)
	}
	//获取流式回复
	stream, err := model.Stream(ctx, message)
	if err != nil {
		panic(err)
	}
	defer stream.Close()

	for {
		chunk, err := stream.Recv()
		if err != nil {
			break
		}
		print(chunk.Content)
	}
	//换行
	println()
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

4. Jinja2

代码:

func main() {
	//这里先使用ollama的方式实现
	ctx := context.Background()
	model, err := ollama.NewChatModel(ctx, &ollama.ChatModelConfig{
		BaseURL: "http://127.0.0.1:11434",
		Model:   "modelscope.cn/Qwen/Qwen3-32B-GGUF:latest",
	})
	if err != nil {
		panic(err)
	}
	//创建message,这个就相当于给大模型的提示词,分为系统输入和用户输入
	//系统输入就是预设的提示词,用户输入就是用户输入的内容
	//message := []*schema.Message{
	//	schema.SystemMessage("你是一个乐于助人的助手"),
	//	schema.UserMessage("请介绍一下Go语言的特点"),
	//}
	template := prompt.FromMessages(
		schema.Jinja2,
		schema.SystemMessage(`{% if level == 'expert' %}你是一个专家级顾问。{% else %}你是一个初级助手。{% endif %}
{% if domain %}你专长于{{ domain }}领域。{% endif %}
请用{% if formal %}正式{% else %}友好{% endif %}的语气回答问题。`),
		schema.UserMessage("{{question}}"),
	)
	//vars := map[string]any{
	//	"isExpert": true,
	//	"domain":   "数据库",
	//	"isFormal": true,
	//	"task":     "提供专业的数据库优化建议",
	//	"question": "如何优化大型数据库的查询性能?",
	//}
	vars := map[string]any{
		"level":    "expert",
		"domain":   "人工智能",
		"formal":   true,
		"question": "请解释Transformer模型的工作原理。",
	}
	message, err := template.Format(ctx, vars)
	for _, v := range message {
		println(v.Content)
	}
	//获取流式回复
	stream, err := model.Stream(ctx, message)
	if err != nil {
		panic(err)
	}
	defer stream.Close()

	for {
		chunk, err := stream.Recv()
		if err != nil {
			break
		}
		print(chunk.Content)
	}
	//换行
	println()
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

5. 对话历史

代码:

func main() {
	//这里先使用ollama的方式实现
	ctx := context.Background()
	model, err := ollama.NewChatModel(ctx, &ollama.ChatModelConfig{
		BaseURL: "http://127.0.0.1:11434",
		Model:   "modelscope.cn/Qwen/Qwen3-32B-GGUF:latest",
	})
	if err != nil {
		panic(err)
	}
	//创建message,这个就相当于给大模型的提示词,分为系统输入和用户输入
	//系统输入就是预设的提示词,用户输入就是用户输入的内容
	//message := []*schema.Message{
	//	schema.SystemMessage("你是一个乐于助人的助手"),
	//	schema.UserMessage("请介绍一下Go语言的特点"),
	//}
	template := prompt.FromMessages(
		schema.GoTemplate,
		schema.SystemMessage(`你是一个{{.role}},你的任务是{{.task}}。
请参考之前的对话历史来回答当前的问题`),
		schema.MessagesPlaceholder("history", false),
		schema.UserMessage("{{.question}}"),
	)
	vars := map[string]any{
		"role": "记忆器",
		"task": "根据用户提供的信息,给出准确的回答,如果历史中有答案,采用用户的答案",
		"history": []*schema.Message{
			schema.UserMessage("你好,我想了解一下Go语言的并发机制"),
			schema.AssistantMessage("Go语言提供了goroutines和channels来支持并发编程。Goroutines是轻量级线程,channels用于goroutines之间的通信。", nil),
			schema.UserMessage("你错了,Go语言只提供了go关键字来支持并发"),
		},
		"question": "Go语言的并发机制",
	}
	message, err := template.Format(ctx, vars)
	for _, v := range message {
		println(v.Content)
	}
	//获取流式回复
	stream, err := model.Stream(ctx, message)
	if err != nil {
		panic(err)
	}
	defer stream.Close()

	for {
		chunk, err := stream.Recv()
		if err != nil {
			break
		}
		print(chunk.Content)
	}
	//换行
	println()
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54