@@ -26,141 +26,58 @@ const (
26
26
genaiRoleModel = "model"
27
27
)
28
28
29
- type GenaiModelAdapter interface {
30
- GenerateContent (ctx context.Context , req * ChatCompletionRequest ) (* openai.ChatCompletionResponse , error )
31
- GenerateStreamContent (ctx context.Context , req * ChatCompletionRequest ) (<- chan string , error )
32
- }
33
-
34
- type GeminiProAdapter struct {
29
+ type GeminiAdapter struct {
35
30
client * genai.Client
36
31
model string
37
32
}
38
33
39
- func NewGeminiProAdapter (client * genai.Client , model string ) GenaiModelAdapter {
40
- return & GeminiProAdapter {
34
+ func NewGeminiAdapter (client * genai.Client , model string ) * GeminiAdapter {
35
+ return & GeminiAdapter {
41
36
client : client ,
42
37
model : model ,
43
38
}
44
39
}
45
40
46
- func (g * GeminiProAdapter ) GenerateContent (
41
+ func (g * GeminiAdapter ) GenerateContent (
47
42
ctx context.Context ,
48
43
req * ChatCompletionRequest ,
44
+ content []* genai.Content ,
49
45
) (* openai.ChatCompletionResponse , error ) {
50
46
model := g .client .GenerativeModel (g .model )
51
47
setGenaiModelByOpenaiRequest (model , req )
52
48
53
49
cs := model .StartChat ()
54
- setGenaiChatByOpenaiRequest (cs , req )
50
+ setGenaiChatHistory (cs , content )
55
51
56
- prompt := genai .Text (req .Messages [len (req .Messages )- 1 ].StringContent ())
57
- genaiResp , err := cs .SendMessage (ctx , prompt )
52
+ genaiResp , err := cs .SendMessage (ctx , content [len (content )- 1 ].Parts ... )
58
53
if err != nil {
59
54
return nil , errors .Wrap (err , "genai send message error" )
60
55
}
61
56
62
- openaiResp := genaiResponseToOpenaiResponse (genaiResp , g .model )
57
+ openaiResp := genaiResponseToOpenaiResponse (g .model , genaiResp )
63
58
return & openaiResp , nil
64
59
}
65
60
66
- func (g * GeminiProAdapter ) GenerateStreamContent (
61
+ func (g * GeminiAdapter ) GenerateStreamContent (
67
62
ctx context.Context ,
68
63
req * ChatCompletionRequest ,
64
+ content []* genai.Content ,
69
65
) (<- chan string , error ) {
70
66
model := g .client .GenerativeModel (g .model )
71
67
setGenaiModelByOpenaiRequest (model , req )
72
68
73
69
cs := model .StartChat ()
74
- setGenaiChatByOpenaiRequest (cs , req )
70
+ setGenaiChatHistory (cs , content )
75
71
76
- prompt := genai .Text (req .Messages [len (req .Messages )- 1 ].StringContent ())
77
- iter := cs .SendMessageStream (ctx , prompt )
72
+ iter := cs .SendMessageStream (ctx , content [len (content )- 1 ].Parts ... )
78
73
79
74
dataChan := make (chan string )
80
- go handleStreamIter (iter , dataChan , g . model )
75
+ go handleStreamIter (g . model , iter , dataChan )
81
76
82
77
return dataChan , nil
83
78
}
84
79
85
- type GeminiProVisionAdapter struct {
86
- client * genai.Client
87
- }
88
-
89
- func NewGeminiProVisionAdapter (client * genai.Client ) GenaiModelAdapter {
90
- return & GeminiProVisionAdapter {
91
- client : client ,
92
- }
93
- }
94
-
95
- func (g * GeminiProVisionAdapter ) GenerateContent (
96
- ctx context.Context ,
97
- req * ChatCompletionRequest ,
98
- ) (* openai.ChatCompletionResponse , error ) {
99
- model := g .client .GenerativeModel (Gemini1ProVision )
100
- setGenaiModelByOpenaiRequest (model , req )
101
-
102
- // NOTE: use last message as prompt, gemini pro vision does not support context
103
- // https://ai.google.dev/tutorials/go_quickstart#multi-turn-conversations-chat
104
- prompt , err := g .openaiMessageToGenaiPrompt (req .Messages [len (req .Messages )- 1 ])
105
- if err != nil {
106
- return nil , errors .Wrap (err , "genai generate prompt error" )
107
- }
108
-
109
- genaiResp , err := model .GenerateContent (ctx , prompt ... )
110
- if err != nil {
111
- return nil , errors .Wrap (err , "genai send message error" )
112
- }
113
-
114
- openaiResp := genaiResponseToOpenaiResponse (genaiResp , Gemini1ProVision )
115
- return & openaiResp , nil
116
- }
117
-
118
- func (* GeminiProVisionAdapter ) openaiMessageToGenaiPrompt (msg ChatCompletionMessage ) ([]genai.Part , error ) {
119
- parts , err := msg .MultiContent ()
120
- if err != nil {
121
- return nil , err
122
- }
123
-
124
- prompt := make ([]genai.Part , 0 , len (parts ))
125
- for _ , part := range parts {
126
- switch part .Type {
127
- case openai .ChatMessagePartTypeText :
128
- prompt = append (prompt , genai .Text (part .Text ))
129
- case openai .ChatMessagePartTypeImageURL :
130
- data , format , err := parseImageURL (part .ImageURL .URL )
131
- if err != nil {
132
- return nil , errors .Wrap (err , "parse image url error" )
133
- }
134
-
135
- prompt = append (prompt , genai .ImageData (format , data ))
136
- }
137
- }
138
- return prompt , nil
139
- }
140
-
141
- func (g * GeminiProVisionAdapter ) GenerateStreamContent (
142
- ctx context.Context ,
143
- req * ChatCompletionRequest ,
144
- ) (<- chan string , error ) {
145
- model := g .client .GenerativeModel (Gemini1ProVision )
146
- setGenaiModelByOpenaiRequest (model , req )
147
-
148
- // NOTE: use last message as prompt, gemini pro vision does not support context
149
- // https://ai.google.dev/tutorials/go_quickstart#multi-turn-conversations-chat
150
- prompt , err := g .openaiMessageToGenaiPrompt (req .Messages [len (req .Messages )- 1 ])
151
- if err != nil {
152
- return nil , errors .Wrap (err , "genai generate prompt error" )
153
- }
154
-
155
- iter := model .GenerateContentStream (ctx , prompt ... )
156
-
157
- dataChan := make (chan string )
158
- go handleStreamIter (iter , dataChan , Gemini1ProVision )
159
-
160
- return dataChan , nil
161
- }
162
-
163
- func handleStreamIter (iter * genai.GenerateContentResponseIterator , dataChan chan string , model string ) {
80
+ func handleStreamIter (model string , iter * genai.GenerateContentResponseIterator , dataChan chan string ) {
164
81
defer close (dataChan )
165
82
166
83
respID := util .GetUUID ()
@@ -184,7 +101,7 @@ func handleStreamIter(iter *genai.GenerateContentResponseIterator, dataChan chan
184
101
break
185
102
}
186
103
187
- openaiResp := genaiResponseToStreamCompletionResponse (genaiResp , respID , created , model )
104
+ openaiResp := genaiResponseToStreamCompletionResponse (model , genaiResp , respID , created )
188
105
resp , _ := json .Marshal (openaiResp )
189
106
dataChan <- string (resp )
190
107
@@ -195,10 +112,10 @@ func handleStreamIter(iter *genai.GenerateContentResponseIterator, dataChan chan
195
112
}
196
113
197
114
func genaiResponseToStreamCompletionResponse (
115
+ model string ,
198
116
genaiResp * genai.GenerateContentResponse ,
199
117
respID string ,
200
118
created int64 ,
201
- model string ,
202
119
) * CompletionResponse {
203
120
resp := CompletionResponse {
204
121
ID : fmt .Sprintf ("chatcmpl-%s" , respID ),
@@ -233,7 +150,7 @@ func genaiResponseToStreamCompletionResponse(
233
150
}
234
151
235
152
func genaiResponseToOpenaiResponse (
236
- genaiResp * genai.GenerateContentResponse , model string ,
153
+ model string , genaiResp * genai.GenerateContentResponse ,
237
154
) openai.ChatCompletionResponse {
238
155
resp := openai.ChatCompletionResponse {
239
156
ID : fmt .Sprintf ("chatcmpl-%s" , util .GetUUID ()),
@@ -275,42 +192,10 @@ func convertFinishReason(reason genai.FinishReason) openai.FinishReason {
275
192
return openaiFinishReason
276
193
}
277
194
278
- func setGenaiChatByOpenaiRequest (cs * genai.ChatSession , req * ChatCompletionRequest ) {
279
- cs .History = make ([]* genai.Content , 0 , len (req .Messages ))
280
- if len (req .Messages ) > 1 {
281
- for _ , message := range req .Messages [:len (req .Messages )- 1 ] {
282
- switch message .Role {
283
- case openai .ChatMessageRoleSystem :
284
- cs .History = append (cs .History , []* genai.Content {
285
- {
286
- Parts : []genai.Part {
287
- genai .Text (message .StringContent ()),
288
- },
289
- Role : genaiRoleUser ,
290
- },
291
- {
292
- Parts : []genai.Part {
293
- genai .Text ("" ),
294
- },
295
- Role : genaiRoleModel ,
296
- },
297
- }... )
298
- case openai .ChatMessageRoleAssistant :
299
- cs .History = append (cs .History , & genai.Content {
300
- Parts : []genai.Part {
301
- genai .Text (message .StringContent ()),
302
- },
303
- Role : genaiRoleModel ,
304
- })
305
- case openai .ChatMessageRoleUser :
306
- cs .History = append (cs .History , & genai.Content {
307
- Parts : []genai.Part {
308
- genai .Text (message .StringContent ()),
309
- },
310
- Role : genaiRoleUser ,
311
- })
312
- }
313
- }
195
+ func setGenaiChatHistory (cs * genai.ChatSession , content []* genai.Content ) {
196
+ cs .History = make ([]* genai.Content , 0 , len (content ))
197
+ if len (content ) > 1 {
198
+ cs .History = content [:len (content )- 1 ]
314
199
}
315
200
316
201
if len (cs .History ) != 0 && cs .History [len (cs .History )- 1 ].Role != genaiRoleModel {
0 commit comments