Fix OpenAIProxy handler

This commit is contained in:
2025-07-26 22:46:07 +02:00
parent 04086b3047
commit 815e45e597
2 changed files with 25 additions and 9 deletions

View File

@@ -1,8 +1,10 @@
package llamactl package llamactl
import ( import (
"bytes"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io"
"net/http" "net/http"
"os/exec" "os/exec"
"strconv" "strconv"
@@ -456,9 +458,17 @@ func (h *Handler) ProxyToInstance() http.HandlerFunc {
// OpenAIProxy godoc // OpenAIProxy godoc
func (h *Handler) OpenAIProxy() http.HandlerFunc { func (h *Handler) OpenAIProxy() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
// Extract model name from request body // Read the entire body first
bodyBytes, err := io.ReadAll(r.Body)
if err != nil {
http.Error(w, "Failed to read request body", http.StatusBadRequest)
return
}
r.Body.Close()
// Parse the body to extract model name
var requestBody map[string]any var requestBody map[string]any
if err := json.NewDecoder(r.Body).Decode(&requestBody); err != nil { if err := json.Unmarshal(bodyBytes, &requestBody); err != nil {
http.Error(w, "Invalid request body", http.StatusBadRequest) http.Error(w, "Invalid request body", http.StatusBadRequest)
return return
} }
@@ -487,6 +497,10 @@ func (h *Handler) OpenAIProxy() http.HandlerFunc {
return return
} }
// Recreate the request body from the bytes we read
r.Body = io.NopCloser(bytes.NewReader(bodyBytes))
r.ContentLength = int64(len(bodyBytes))
proxy.ServeHTTP(w, r) proxy.ServeHTTP(w, r)
} }
} }

View File

@@ -50,13 +50,15 @@ func SetupRouter(handler *Handler) *chi.Mux {
}) })
}) })
// OpenAI-compatible endpoints (model name in request body determines routing) // OpenAI-compatible proxy endpoint
r.Post("/v1/", handler.OpenAIProxy()) // Proxy to OpenAI-compatible endpoints based on instance name in request body // Handles all POST requests to /v1/*, including:
// r.Post("/v1/completions", handler.OpenAICompletions()) // - /v1/completions
// r.Post("/v1/chat/completions", handler.OpenAIChatCompletions()) // - /v1/chat/completions
// r.Post("/v1/embeddings", handler.OpenAIEmbeddings()) // - /v1/embeddings
// r.Post("/v1/rerank", handler.OpenAIRerank()) // - /v1/rerank
// r.Post("/v1/reranking", handler.OpenAIReranking()) // - /v1/reranking
// The instance/model to use is determined by the request body.
r.Post("/v1/*", handler.OpenAIProxy())
// Serve WebUI files // Serve WebUI files
if err := webui.SetupWebUI(r); err != nil { if err := webui.SetupWebUI(r); err != nil {