Skip to content

Commit 7d62378

Browse files
committed
Review fixes added
1 parent e471356 commit 7d62378

File tree

5 files changed

+1075
-275
lines changed

5 files changed

+1075
-275
lines changed

core/providers/ollama/chat.go

Lines changed: 5 additions & 229 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,6 @@
33
package ollama
44

55
import (
6-
"encoding/base64"
7-
"encoding/json"
8-
"strings"
9-
106
"github.com/maximhq/bifrost/core/schemas"
117
)
128

@@ -126,6 +122,11 @@ func ToOllamaChatRequest(bifrostReq *schemas.BifrostChatRequest) *OllamaChatRequ
126122
if keepAlive, ok := schemas.SafeExtractStringPointer(bifrostReq.Params.ExtraParams["keep_alive"]); ok {
127123
ollamaReq.KeepAlive = keepAlive
128124
}
125+
126+
// Enable thinking mode (for thinking-specific models)
127+
if think, ok := schemas.SafeExtractBoolPointer(bifrostReq.Params.ExtraParams["think"]); ok {
128+
ollamaReq.Think = think
129+
}
129130
}
130131

131132
if hasOptions {
@@ -153,146 +154,6 @@ func ToOllamaChatRequest(bifrostReq *schemas.BifrostChatRequest) *OllamaChatRequ
153154
return ollamaReq
154155
}
155156

156-
// convertMessagesToOllama converts Bifrost messages to Ollama format.
157-
func convertMessagesToOllama(messages []schemas.ChatMessage) []OllamaMessage {
158-
var ollamaMessages []OllamaMessage
159-
160-
for _, msg := range messages {
161-
ollamaMsg := OllamaMessage{
162-
Role: string(msg.Role),
163-
}
164-
165-
// Handle content
166-
if msg.Content != nil {
167-
if msg.Content.ContentStr != nil {
168-
ollamaMsg.Content = *msg.Content.ContentStr
169-
} else if msg.Content.ContentBlocks != nil {
170-
var textParts []string
171-
var images []string
172-
173-
for _, block := range msg.Content.ContentBlocks {
174-
switch block.Type {
175-
case schemas.ChatContentBlockTypeText:
176-
if block.Text != nil {
177-
textParts = append(textParts, *block.Text)
178-
}
179-
case schemas.ChatContentBlockTypeImage:
180-
if block.ImageURLStruct != nil {
181-
// Handle image URLs - extract base64 data
182-
imageData := extractBase64Image(block.ImageURLStruct.URL)
183-
if imageData != "" {
184-
images = append(images, imageData)
185-
}
186-
}
187-
}
188-
}
189-
190-
ollamaMsg.Content = strings.Join(textParts, "\n")
191-
if len(images) > 0 {
192-
ollamaMsg.Images = images
193-
}
194-
}
195-
}
196-
197-
// Handle tool calls for assistant messages
198-
if msg.ChatAssistantMessage != nil && msg.ChatAssistantMessage.ToolCalls != nil {
199-
for _, tc := range msg.ChatAssistantMessage.ToolCalls {
200-
var args map[string]interface{}
201-
if tc.Function.Arguments != "" {
202-
_ = json.Unmarshal([]byte(tc.Function.Arguments), &args)
203-
}
204-
if args == nil {
205-
args = make(map[string]interface{})
206-
}
207-
208-
name := ""
209-
if tc.Function.Name != nil {
210-
name = *tc.Function.Name
211-
}
212-
213-
ollamaMsg.ToolCalls = append(ollamaMsg.ToolCalls, OllamaToolCall{
214-
Function: OllamaToolCallFunction{
215-
Name: name,
216-
Arguments: args,
217-
},
218-
})
219-
}
220-
}
221-
222-
// Handle tool response messages
223-
if msg.Role == schemas.ChatMessageRoleTool && msg.ChatToolMessage != nil {
224-
// In Ollama, tool responses are regular messages with role "tool"
225-
// The content is the tool's response
226-
if msg.Content != nil && msg.Content.ContentStr != nil {
227-
ollamaMsg.Content = *msg.Content.ContentStr
228-
}
229-
}
230-
231-
ollamaMessages = append(ollamaMessages, ollamaMsg)
232-
}
233-
234-
return ollamaMessages
235-
}
236-
237-
// extractBase64Image extracts base64 data from a data URL or returns the URL as-is for base64.
238-
func extractBase64Image(url string) string {
239-
// Handle data URLs: data:image/jpeg;base64,/9j/4AAQ...
240-
if strings.HasPrefix(url, "data:") {
241-
parts := strings.SplitN(url, ",", 2)
242-
if len(parts) == 2 {
243-
return parts[1] // Return just the base64 data
244-
}
245-
}
246-
247-
// If it's already base64 encoded (no prefix), return as-is
248-
if isBase64(url) {
249-
return url
250-
}
251-
252-
// For regular URLs, Ollama doesn't support them directly
253-
// The caller should handle URL-to-base64 conversion if needed
254-
return ""
255-
}
256-
257-
// isBase64 checks if a string is likely base64 encoded.
258-
func isBase64(s string) bool {
259-
if len(s) < 4 {
260-
return false
261-
}
262-
_, err := base64.StdEncoding.DecodeString(s)
263-
return err == nil
264-
}
265-
266-
// convertToolsToOllama converts Bifrost tools to Ollama format.
267-
func convertToolsToOllama(tools []schemas.ChatTool) []OllamaTool {
268-
var ollamaTools []OllamaTool
269-
270-
for _, tool := range tools {
271-
if tool.Function == nil {
272-
continue
273-
}
274-
275-
ollamaTool := OllamaTool{
276-
Type: "function",
277-
Function: OllamaToolFunction{
278-
Name: tool.Function.Name,
279-
},
280-
}
281-
282-
if tool.Function.Description != nil {
283-
ollamaTool.Function.Description = *tool.Function.Description
284-
}
285-
286-
if tool.Function.Parameters != nil {
287-
ollamaTool.Function.Parameters = tool.Function.Parameters
288-
}
289-
290-
ollamaTools = append(ollamaTools, ollamaTool)
291-
}
292-
293-
return ollamaTools
294-
}
295-
296157
// ToBifrostChatRequest converts an Ollama chat request to Bifrost format.
297158
// This is used for passthrough/reverse conversion scenarios.
298159
func (r *OllamaChatRequest) ToBifrostChatRequest() *schemas.BifrostChatRequest {
@@ -360,88 +221,3 @@ func (r *OllamaChatRequest) ToBifrostChatRequest() *schemas.BifrostChatRequest {
360221

361222
return bifrostReq
362223
}
363-
364-
// convertMessagesFromOllama converts Ollama messages to Bifrost format.
365-
func convertMessagesFromOllama(messages []OllamaMessage) []schemas.ChatMessage {
366-
var bifrostMessages []schemas.ChatMessage
367-
368-
for _, msg := range messages {
369-
bifrostMsg := schemas.ChatMessage{
370-
Role: schemas.ChatMessageRole(msg.Role),
371-
Content: &schemas.ChatMessageContent{
372-
ContentStr: &msg.Content,
373-
},
374-
}
375-
376-
// Handle tool calls
377-
if len(msg.ToolCalls) > 0 {
378-
var toolCalls []schemas.ChatAssistantMessageToolCall
379-
for i, tc := range msg.ToolCalls {
380-
args, _ := json.Marshal(tc.Function.Arguments)
381-
toolCalls = append(toolCalls, schemas.ChatAssistantMessageToolCall{
382-
Index: uint16(i),
383-
Type: schemas.Ptr("function"),
384-
ID: schemas.Ptr(tc.Function.Name),
385-
Function: schemas.ChatAssistantMessageToolCallFunction{
386-
Name: &tc.Function.Name,
387-
Arguments: string(args),
388-
},
389-
})
390-
}
391-
bifrostMsg.ChatAssistantMessage = &schemas.ChatAssistantMessage{
392-
ToolCalls: toolCalls,
393-
}
394-
}
395-
396-
// Handle images
397-
if len(msg.Images) > 0 {
398-
var contentBlocks []schemas.ChatContentBlock
399-
400-
// Add text content if present
401-
if msg.Content != "" {
402-
contentBlocks = append(contentBlocks, schemas.ChatContentBlock{
403-
Type: schemas.ChatContentBlockTypeText,
404-
Text: &msg.Content,
405-
})
406-
}
407-
408-
// Add images
409-
for _, img := range msg.Images {
410-
dataURL := "data:image/jpeg;base64," + img
411-
contentBlocks = append(contentBlocks, schemas.ChatContentBlock{
412-
Type: schemas.ChatContentBlockTypeImage,
413-
ImageURLStruct: &schemas.ChatInputImage{
414-
URL: dataURL,
415-
},
416-
})
417-
}
418-
419-
bifrostMsg.Content = &schemas.ChatMessageContent{
420-
ContentBlocks: contentBlocks,
421-
}
422-
}
423-
424-
bifrostMessages = append(bifrostMessages, bifrostMsg)
425-
}
426-
427-
return bifrostMessages
428-
}
429-
430-
// convertToolsFromOllama converts Ollama tools to Bifrost format.
431-
func convertToolsFromOllama(tools []OllamaTool) []schemas.ChatTool {
432-
var bifrostTools []schemas.ChatTool
433-
434-
for _, tool := range tools {
435-
bifrostTool := schemas.ChatTool{
436-
Type: schemas.ChatToolTypeFunction,
437-
Function: &schemas.ChatToolFunction{
438-
Name: tool.Function.Name,
439-
Description: &tool.Function.Description,
440-
Parameters: tool.Function.Parameters,
441-
},
442-
}
443-
bifrostTools = append(bifrostTools, bifrostTool)
444-
}
445-
446-
return bifrostTools
447-
}

0 commit comments

Comments
 (0)