1
- use std:: fs:: File ;
2
- use std:: io:: Read ;
3
- use std:: sync:: Arc ;
1
+ use crate :: routes:: chat:: ChatCompletionMessageParams ;
4
2
use anyhow:: bail;
5
3
use liquid:: { ParserBuilder , Template } ;
6
4
use serde:: Serialize ;
7
- use crate :: routes:: chat:: ChatCompletionMessageParams ;
5
+ use std:: fs:: File ;
6
+ use std:: io:: Read ;
7
+ use std:: sync:: Arc ;
8
8
9
- const DEFAULT_TEMPLATE : & str =
10
- "{% for item in items %}\
9
+ const DEFAULT_TEMPLATE : & str = "{% for item in items %}\
11
10
{{ item.identity }}{% if item.name %} {{ item.name }}{% endif %}: {{ item.content }}
12
11
{% endfor %}\
13
12
ASSISTANT:";
14
13
15
14
#[ derive( Clone ) ]
16
15
pub struct HistoryBuilder {
17
- history_template : Arc < Template >
16
+ history_template : Arc < Template > ,
18
17
}
19
18
20
19
impl HistoryBuilder {
@@ -24,12 +23,11 @@ impl HistoryBuilder {
24
23
}
25
24
let mut _ref_holder = None ;
26
25
27
-
28
26
let template = match template_file {
29
27
None => match template {
30
- None => { DEFAULT_TEMPLATE }
31
- Some ( cfg) => { cfg. as_str ( ) }
32
- }
28
+ None => DEFAULT_TEMPLATE ,
29
+ Some ( cfg) => cfg. as_str ( ) ,
30
+ } ,
33
31
Some ( filename) => {
34
32
_ref_holder = Some ( load_template_file ( filename) ?) ;
35
33
_ref_holder. as_ref ( ) . unwrap ( ) . as_str ( )
@@ -38,10 +36,13 @@ impl HistoryBuilder {
38
36
39
37
let history_template = Arc :: new ( ParserBuilder :: with_stdlib ( ) . build ( ) ?. parse ( template) ?) ;
40
38
41
- Ok ( HistoryBuilder { history_template} )
39
+ Ok ( HistoryBuilder { history_template } )
42
40
}
43
41
44
- pub fn build_history ( & self , messages : & Vec < ChatCompletionMessageParams > ) -> anyhow:: Result < String > {
42
+ pub fn build_history (
43
+ & self ,
44
+ messages : & Vec < ChatCompletionMessageParams > ,
45
+ ) -> anyhow:: Result < String > {
45
46
let items: Vec < _ > = messages. iter ( ) . map ( |x| HistoryItem :: new ( x) ) . collect ( ) ;
46
47
let context = liquid:: object!( { "items" : items} ) ;
47
48
Ok ( self . history_template . render ( & context) ?)
@@ -59,19 +60,31 @@ fn load_template_file(file: &String) -> anyhow::Result<String> {
59
60
struct HistoryItem {
60
61
identity : String ,
61
62
content : String ,
62
- name : Option < String >
63
+ name : Option < String > ,
63
64
}
64
65
65
66
impl HistoryItem {
66
67
pub fn new ( message : & ChatCompletionMessageParams ) -> Self {
67
68
let ( identity, content, name) = match message {
68
- ChatCompletionMessageParams :: System { content, name } => { ( "System" . into ( ) , content. clone ( ) , name. clone ( ) ) }
69
- ChatCompletionMessageParams :: User { content, name } => { ( "User" . into ( ) , content. clone ( ) , name. clone ( ) ) }
70
- ChatCompletionMessageParams :: Assistant { content } => { ( "Assistant" . into ( ) , content. clone ( ) , None ) }
71
- ChatCompletionMessageParams :: Tool { content, .. } => { ( "Tool" . into ( ) , content. clone ( ) , None ) }
69
+ ChatCompletionMessageParams :: System { content, name } => {
70
+ ( "System" . into ( ) , content. clone ( ) , name. clone ( ) )
71
+ }
72
+ ChatCompletionMessageParams :: User { content, name } => {
73
+ ( "User" . into ( ) , content. clone ( ) , name. clone ( ) )
74
+ }
75
+ ChatCompletionMessageParams :: Assistant { content } => {
76
+ ( "Assistant" . into ( ) , content. clone ( ) , None )
77
+ }
78
+ ChatCompletionMessageParams :: Tool { content, .. } => {
79
+ ( "Tool" . into ( ) , content. clone ( ) , None )
80
+ }
72
81
} ;
73
82
74
- HistoryItem { identity, content, name }
83
+ HistoryItem {
84
+ identity,
85
+ content,
86
+ name,
87
+ }
75
88
}
76
89
}
77
90
@@ -83,100 +96,169 @@ mod test {
83
96
pub fn test_default_template ( ) {
84
97
let template = None ;
85
98
let template_file = None ;
86
- let builder = HistoryBuilder :: new ( & template, & template_file) . expect ( "default template should build correctly" ) ;
99
+ let builder = HistoryBuilder :: new ( & template, & template_file)
100
+ . expect ( "default template should build correctly" ) ;
87
101
88
102
let messages = vec ! [
89
- ChatCompletionMessageParams :: System { content: "test system 1" . into( ) , name: Some ( "system 1" . into( ) ) } ,
90
- ChatCompletionMessageParams :: System { content: "test system 2" . into( ) , name: None } ,
91
- ChatCompletionMessageParams :: Assistant { content: "test assistant 1" . into( ) } ,
92
- ChatCompletionMessageParams :: Tool { content: "test tool 1" . into( ) , tool_call_id: "tool_1" . into( ) } ,
93
- ChatCompletionMessageParams :: User { content: "test user 1" . into( ) , name: Some ( "user 1" . into( ) ) } ,
94
- ChatCompletionMessageParams :: User { content: "test user 2" . into( ) , name: None }
103
+ ChatCompletionMessageParams :: System {
104
+ content: "test system 1" . into( ) ,
105
+ name: Some ( "system 1" . into( ) ) ,
106
+ } ,
107
+ ChatCompletionMessageParams :: System {
108
+ content: "test system 2" . into( ) ,
109
+ name: None ,
110
+ } ,
111
+ ChatCompletionMessageParams :: Assistant {
112
+ content: "test assistant 1" . into( ) ,
113
+ } ,
114
+ ChatCompletionMessageParams :: Tool {
115
+ content: "test tool 1" . into( ) ,
116
+ tool_call_id: "tool_1" . into( ) ,
117
+ } ,
118
+ ChatCompletionMessageParams :: User {
119
+ content: "test user 1" . into( ) ,
120
+ name: Some ( "user 1" . into( ) ) ,
121
+ } ,
122
+ ChatCompletionMessageParams :: User {
123
+ content: "test user 2" . into( ) ,
124
+ name: None ,
125
+ } ,
95
126
] ;
96
127
97
- let result = builder. build_history ( & messages) . expect ( "history should build correctly" ) ;
128
+ let result = builder
129
+ . build_history ( & messages)
130
+ . expect ( "history should build correctly" ) ;
98
131
99
- let expected_result: String =
100
- "System system 1: test system 1
132
+ let expected_result: String = "System system 1: test system 1
101
133
System: test system 2
102
134
Assistant: test assistant 1
103
135
Tool: test tool 1
104
136
User user 1: test user 1
105
137
User: test user 2
106
- ASSISTANT:" . into ( ) ;
138
+ ASSISTANT:"
139
+ . into ( ) ;
107
140
108
141
assert_eq ! ( expected_result, result)
109
-
110
142
}
111
143
112
144
#[ test]
113
145
pub fn test_template_file ( ) {
114
146
let template = None ;
115
- let template_file = Some ( format ! ( "{}/example/history_template.liquid" , env!( "CARGO_MANIFEST_DIR" ) ) ) ;
116
- let builder = HistoryBuilder :: new ( & template, & template_file) . expect ( "default template should build correctly" ) ;
147
+ let template_file = Some ( format ! (
148
+ "{}/example/history_template.liquid" ,
149
+ env!( "CARGO_MANIFEST_DIR" )
150
+ ) ) ;
151
+ let builder = HistoryBuilder :: new ( & template, & template_file)
152
+ . expect ( "default template should build correctly" ) ;
117
153
118
154
let messages = vec ! [
119
- ChatCompletionMessageParams :: System { content: "test system 1" . into( ) , name: Some ( "system 1" . into( ) ) } ,
120
- ChatCompletionMessageParams :: System { content: "test system 2" . into( ) , name: None } ,
121
- ChatCompletionMessageParams :: Assistant { content: "test assistant 1" . into( ) } ,
122
- ChatCompletionMessageParams :: Tool { content: "test tool 1" . into( ) , tool_call_id: "tool_1" . into( ) } ,
123
- ChatCompletionMessageParams :: User { content: "test user 1" . into( ) , name: Some ( "user 1" . into( ) ) } ,
124
- ChatCompletionMessageParams :: User { content: "test user 2" . into( ) , name: None }
155
+ ChatCompletionMessageParams :: System {
156
+ content: "test system 1" . into( ) ,
157
+ name: Some ( "system 1" . into( ) ) ,
158
+ } ,
159
+ ChatCompletionMessageParams :: System {
160
+ content: "test system 2" . into( ) ,
161
+ name: None ,
162
+ } ,
163
+ ChatCompletionMessageParams :: Assistant {
164
+ content: "test assistant 1" . into( ) ,
165
+ } ,
166
+ ChatCompletionMessageParams :: Tool {
167
+ content: "test tool 1" . into( ) ,
168
+ tool_call_id: "tool_1" . into( ) ,
169
+ } ,
170
+ ChatCompletionMessageParams :: User {
171
+ content: "test user 1" . into( ) ,
172
+ name: Some ( "user 1" . into( ) ) ,
173
+ } ,
174
+ ChatCompletionMessageParams :: User {
175
+ content: "test user 2" . into( ) ,
176
+ name: None ,
177
+ } ,
125
178
] ;
126
179
127
- let result = builder. build_history ( & messages) . expect ( "history should build correctly" ) ;
180
+ let result = builder
181
+ . build_history ( & messages)
182
+ . expect ( "history should build correctly" ) ;
128
183
129
- let expected_result: String =
130
- "System system 1: test system 1
184
+ let expected_result: String = "System system 1: test system 1
131
185
System: test system 2
132
186
Assistant: test assistant 1
133
187
Tool: test tool 1
134
188
User user 1: test user 1
135
189
User: test user 2
136
- ASSISTANT:" . into ( ) ;
190
+ ASSISTANT:"
191
+ . into ( ) ;
137
192
138
193
assert_eq ! ( expected_result, result)
139
-
140
194
}
141
195
142
196
#[ test]
143
197
pub fn test_template_file_custom_roles ( ) {
144
198
let template = None ;
145
- let template_file = Some ( format ! ( "{}/example/history_template_custom_roles.liquid" , env!( "CARGO_MANIFEST_DIR" ) ) ) ;
146
- let builder = HistoryBuilder :: new ( & template, & template_file) . expect ( "default template should build correctly" ) ;
199
+ let template_file = Some ( format ! (
200
+ "{}/example/history_template_custom_roles.liquid" ,
201
+ env!( "CARGO_MANIFEST_DIR" )
202
+ ) ) ;
203
+ let builder = HistoryBuilder :: new ( & template, & template_file)
204
+ . expect ( "default template should build correctly" ) ;
147
205
148
206
let messages = vec ! [
149
- ChatCompletionMessageParams :: System { content: "test system 1" . into( ) , name: Some ( "system 1" . into( ) ) } ,
150
- ChatCompletionMessageParams :: System { content: "test system 2" . into( ) , name: None } ,
151
- ChatCompletionMessageParams :: Assistant { content: "test assistant 1" . into( ) } ,
152
- ChatCompletionMessageParams :: Tool { content: "test tool 1" . into( ) , tool_call_id: "tool_1" . into( ) } ,
153
- ChatCompletionMessageParams :: User { content: "test user 1" . into( ) , name: Some ( "user 1" . into( ) ) } ,
154
- ChatCompletionMessageParams :: User { content: "test user 2" . into( ) , name: None }
207
+ ChatCompletionMessageParams :: System {
208
+ content: "test system 1" . into( ) ,
209
+ name: Some ( "system 1" . into( ) ) ,
210
+ } ,
211
+ ChatCompletionMessageParams :: System {
212
+ content: "test system 2" . into( ) ,
213
+ name: None ,
214
+ } ,
215
+ ChatCompletionMessageParams :: Assistant {
216
+ content: "test assistant 1" . into( ) ,
217
+ } ,
218
+ ChatCompletionMessageParams :: Tool {
219
+ content: "test tool 1" . into( ) ,
220
+ tool_call_id: "tool_1" . into( ) ,
221
+ } ,
222
+ ChatCompletionMessageParams :: User {
223
+ content: "test user 1" . into( ) ,
224
+ name: Some ( "user 1" . into( ) ) ,
225
+ } ,
226
+ ChatCompletionMessageParams :: User {
227
+ content: "test user 2" . into( ) ,
228
+ name: None ,
229
+ } ,
155
230
] ;
156
231
157
- let result = builder. build_history ( & messages) . expect ( "history should build correctly" ) ;
232
+ let result = builder
233
+ . build_history ( & messages)
234
+ . expect ( "history should build correctly" ) ;
158
235
159
- let expected_result: String =
160
- "Robot system 1: test system 1
236
+ let expected_result: String = "Robot system 1: test system 1
161
237
Robot: test system 2
162
238
Support: test assistant 1
163
239
Robot: test tool 1
164
240
Customer user 1: test user 1
165
241
Customer: test user 2
166
- ASSISTANT:" . into ( ) ;
242
+ ASSISTANT:"
243
+ . into ( ) ;
167
244
168
245
assert_eq ! ( expected_result, result)
169
-
170
246
}
171
247
172
248
#[ test]
173
249
pub fn test_validations ( ) {
174
250
let template = Some ( "abc" . into ( ) ) ;
175
251
let template_file = Some ( "abc" . into ( ) ) ;
176
252
match HistoryBuilder :: new ( & template, & template_file) {
177
- Ok ( _) => { assert ! ( false , "expected err" ) }
178
- Err ( e) => { assert_eq ! ( "cannot set both history-template and history-template-file" , e. to_string( ) ) }
253
+ Ok ( _) => {
254
+ assert ! ( false , "expected err" )
255
+ }
256
+ Err ( e) => {
257
+ assert_eq ! (
258
+ "cannot set both history-template and history-template-file" ,
259
+ e. to_string( )
260
+ )
261
+ }
179
262
} ;
180
-
181
263
}
182
- }
264
+ }
0 commit comments