// fake_ollama is a minimal Ollama-API-compatible fake for proof harness // fixture-mode smokes (R-006 partial). Implements just enough of the // Ollama API surface for embedd to drive end-to-end without a real // Ollama installation: // // GET /api/tags — returns a fixed model list including // nomic-embed-text:latest // POST /api/embeddings — returns a deterministic dim-D vector // derived from sha256(prompt). Same prompt // → bit-identical vector across runs. // // Vectors are NOT semantically meaningful (the value of similarity // search against these is undefined). The fake is for proving the // EMBED CONTRACT — dimension echo, response shape, status codes — // not for proving real semantic ranking. That requires real Ollama. // // Why this exists: the proof harness's contract tier already runs // against real Ollama (when present). For CI / fresh-clone reviewers // without Ollama, this fake unblocks the chain. // // Usage: // bin/fake_ollama --bind 127.0.0.1:11435 --dim 768 package main import ( "crypto/sha256" "encoding/json" "flag" "fmt" "log/slog" "net/http" "os" ) func main() { bind := flag.String("bind", "127.0.0.1:11435", "bind addr") dim := flag.Int("dim", 768, "embedding dimension to return") model := flag.String("model", "nomic-embed-text", "model name to echo back") flag.Parse() mux := http.NewServeMux() mux.HandleFunc("/api/tags", func(w http.ResponseWriter, _ *http.Request) { w.Header().Set("Content-Type", "application/json") _ = json.NewEncoder(w).Encode(map[string]any{ "models": []map[string]any{ { "name": *model + ":latest", "model": *model + ":latest", }, }, }) }) mux.HandleFunc("/api/embeddings", func(w http.ResponseWriter, r *http.Request) { var req struct { Model string `json:"model"` Prompt string `json:"prompt"` } if err := json.NewDecoder(r.Body).Decode(&req); err != nil { http.Error(w, "decode: "+err.Error(), http.StatusBadRequest) return } // Reject unknown models so embedd's bad-model→502 contract // path is exercisable. The fake recognizes the configured // model name only. if req.Model != "" && req.Model != *model && req.Model != *model+":latest" { http.Error(w, fmt.Sprintf("model %q not found", req.Model), http.StatusNotFound) return } vec := deterministicVector(req.Prompt, *dim) w.Header().Set("Content-Type", "application/json") _ = json.NewEncoder(w).Encode(map[string]any{ "embedding": vec, }) }) mux.HandleFunc("/health", func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusOK) _, _ = w.Write([]byte(`{"status":"ok","service":"fake_ollama"}`)) }) slog.Info("fake_ollama starting", "bind", *bind, "dim", *dim, "model", *model) srv := &http.Server{Addr: *bind, Handler: mux} if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { slog.Error("fake_ollama serve", "err", err) os.Exit(1) } } // deterministicVector returns a fixed dim-d float64 vector derived // from sha256(prompt). Same prompt → same vector across runs and // across machines, so smoke assertions can compare to fixtures. func deterministicVector(prompt string, dim int) []float64 { h := sha256.Sum256([]byte(prompt)) vec := make([]float64, dim) for i := range vec { // Spread the 32 hash bytes across `dim` positions; map to // [-1, 1] so cosine distance is well-defined and the result // looks vaguely like a real embedding. b := h[i%len(h)] vec[i] = (float64(b) - 128.0) / 128.0 } return vec }