Skip to content

Commit ef6dd45

Browse files
committed
Implement Ollama non stream chat API
1 parent 16a770e commit ef6dd45

1 file changed

Lines changed: 74 additions & 1 deletion

File tree

Tool/Sources/OpenAIService/APIs/OlamaService.swift

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,80 @@ public actor OllamaService {
2828

2929
extension OllamaService: ChatCompletionsAPI {
3030
func callAsFunction() async throws -> ChatCompletionResponseBody {
31-
fatalError()
31+
let requestBody = ChatCompletionRequestBody(
32+
model: model.info.modelName,
33+
messages: requestBody.messages.map { message in
34+
.init(role: {
35+
switch message.role {
36+
case .assistant:
37+
return .assistant
38+
case .user:
39+
return .user
40+
case .system:
41+
return .system
42+
case .function:
43+
return .user
44+
}
45+
}(), content: message.content)
46+
},
47+
stream: false,
48+
options: .init(
49+
temperature: requestBody.temperature,
50+
stop: requestBody.stop,
51+
num_predict: requestBody.max_tokens
52+
),
53+
keep_alive: nil,
54+
format: nil
55+
)
56+
57+
var request = URLRequest(url: endpoint)
58+
request.httpMethod = "POST"
59+
let encoder = JSONEncoder()
60+
request.httpBody = try encoder.encode(requestBody)
61+
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
62+
let (result, response) = try await URLSession.shared.data(for: request)
63+
64+
guard let response = response as? HTTPURLResponse else {
65+
throw CancellationError()
66+
}
67+
68+
guard response.statusCode == 200 else {
69+
let text = String(data: result, encoding: .utf8)
70+
throw Error.otherError(text ?? "Unknown error")
71+
}
72+
73+
let body = try JSONDecoder().decode(
74+
ChatCompletionResponseChunk.self,
75+
from: result
76+
)
77+
78+
return .init(
79+
object: body.model,
80+
model: body.model,
81+
usage: .init(
82+
prompt_tokens: body.prompt_eval_count ?? 0,
83+
completion_tokens: body.eval_count ?? 0,
84+
total_tokens: (body.eval_count ?? 0) + (body.prompt_eval_count ?? 0)
85+
),
86+
choices: [
87+
.init(
88+
message: body.message.map { message in
89+
.init(role: {
90+
switch message.role {
91+
case .assistant:
92+
return .assistant
93+
case .user:
94+
return .user
95+
case .system:
96+
return .system
97+
}
98+
}(), content: message.content)
99+
} ?? .init(role: .assistant),
100+
index: 0,
101+
finish_reason: ""
102+
),
103+
]
104+
)
32105
}
33106
}
34107

0 commit comments

Comments
 (0)