in ollama/ollama.go [41:103]
func (h *handlers) generateHandler(w http.ResponseWriter, r *http.Request) {
body, err := io.ReadAll(r.Body)
if err != nil {
internal.ErrorHandler(w, r, http.StatusInternalServerError, "failed to read request body: %v", err)
return
}
defer r.Body.Close()
var req GenerateRequest
if err := json.Unmarshal(body, &req); err != nil {
internal.ErrorHandler(w, r, http.StatusInternalServerError, "failed to unmarshal request body: %v", err)
return
}
model := h.client.GenerativeModel(req.Model)
model.GenerationConfig = genai.GenerationConfig{
Temperature: req.Options.Temperature,
MaxOutputTokens: req.Options.NumPredict,
TopK: req.Options.TopK,
TopP: req.Options.TopP,
}
if req.Options.Stop != nil {
model.GenerationConfig.StopSequences = []string{*req.Options.Stop}
}
if req.System != "" {
model.SystemInstruction = &genai.Content{
Role: "system",
Parts: []genai.Part{genai.Text(req.System)},
}
}
parts := []genai.Part{genai.Text(req.Prompt)}
gresp, err := model.GenerateContent(r.Context(), parts...)
if err != nil {
internal.ErrorHandler(w, r, http.StatusInternalServerError, "failed to generate content: %v", err)
return
}
if len(gresp.Candidates) == 0 {
internal.ErrorHandler(w, r, http.StatusInternalServerError, "no candidates returned")
return
}
responseBuilder := &strings.Builder{}
for _, part := range gresp.Candidates[0].Content.Parts {
switch v := part.(type) {
case genai.Text:
responseBuilder.WriteString(string(v))
default:
internal.ErrorHandler(w, r, http.StatusInternalServerError, "unsupported part type: %T", v)
return
}
}
if err := json.NewEncoder(w).Encode(&GenerateResponse{
Model: req.Model,
Response: responseBuilder.String(),
CreatedAt: time.Now(),
PromptEvalCount: gresp.UsageMetadata.PromptTokenCount,
EvalCount: gresp.UsageMetadata.TotalTokenCount,
Done: true,
}); err != nil {
internal.ErrorHandler(w, r, http.StatusInternalServerError, "failed to encode generate response: %v", err)
return
}
}