chore: establish local platform baseline

This commit is contained in:
Codex Local
2026-08-26 06:41:54 +08:00
commit 29bdf4900f
575 changed files with 95644 additions and 0 deletions
+127
View File
@@ -0,0 +1,127 @@
package embeddingprovider
import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"io"
"math"
"net/http"
"net/url"
"strings"
"time"
"data-terminal-cloud/internal/developmentembedding"
"data-terminal-cloud/internal/outbox"
)
const Dimensions = developmentembedding.Dimensions
type Result struct {
Vector []float64
ProviderRef string
}
type Provider interface {
Embed(context.Context, string) (Result, error)
}
type Local struct{}
func (Local) Embed(_ context.Context, content string) (Result, error) {
if strings.TrimSpace(content) == "" {
return Result{}, errors.New("embedding content is required")
}
return Result{Vector: developmentembedding.Vector(content), ProviderRef: "local-deterministic-hash-v1"}, nil
}
type Ark struct {
endpoint string
apiKey string
model string
client *http.Client
}
func NewArk(baseURL, apiKey, model string, timeout time.Duration) (*Ark, error) {
baseURL = strings.TrimRight(strings.TrimSpace(baseURL), "/")
apiKey = strings.TrimSpace(apiKey)
model = strings.TrimSpace(model)
parsed, err := url.Parse(baseURL)
if err != nil || parsed.Host == "" || (parsed.Scheme != "http" && parsed.Scheme != "https") {
return nil, errors.New("Ark base URL must be an absolute HTTP(S) URL")
}
if apiKey == "" || model == "" || timeout <= 0 {
return nil, errors.New("Ark API key, embedding model and positive timeout are required")
}
return &Ark{endpoint: baseURL + "/embeddings", apiKey: apiKey, model: model, client: &http.Client{Timeout: timeout}}, nil
}
func (a *Ark) Embed(ctx context.Context, content string) (Result, error) {
content = strings.TrimSpace(content)
if content == "" {
return Result{}, errors.New("embedding content is required")
}
body, err := json.Marshal(map[string]any{
"model": a.model, "input": content, "encoding_format": "float", "dimensions": Dimensions,
})
if err != nil {
return Result{}, err
}
req, err := http.NewRequestWithContext(ctx, http.MethodPost, a.endpoint, bytes.NewReader(body))
if err != nil {
return Result{}, fmt.Errorf("build Ark embedding request: %w", err)
}
req.Header.Set("Authorization", "Bearer "+a.apiKey)
req.Header.Set("Content-Type", "application/json")
req.Header.Set("User-Agent", "voice-platform-memory-embedding/1.0")
resp, err := a.client.Do(req)
if err != nil {
return Result{}, outbox.Retryable(fmt.Errorf("call Ark embedding model: %w", err))
}
defer resp.Body.Close()
responseBody, readErr := io.ReadAll(io.LimitReader(resp.Body, 4<<20))
if readErr != nil {
return Result{}, outbox.Retryable(fmt.Errorf("read Ark embedding response: %w", readErr))
}
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
requestErr := fmt.Errorf("Ark embedding model returned HTTP %d", resp.StatusCode)
if resp.StatusCode == http.StatusRequestTimeout || resp.StatusCode == http.StatusTooEarly || resp.StatusCode == http.StatusTooManyRequests || resp.StatusCode >= 500 {
return Result{}, outbox.Retryable(requestErr)
}
return Result{}, requestErr
}
var response struct {
Data []struct {
Index int `json:"index"`
Embedding []float64 `json:"embedding"`
} `json:"data"`
}
if err = json.Unmarshal(responseBody, &response); err != nil || len(response.Data) != 1 || response.Data[0].Index != 0 {
return Result{}, outbox.Retryable(errors.New("Ark embedding response has no usable vector"))
}
if err = Validate(response.Data[0].Embedding); err != nil {
return Result{}, outbox.Retryable(err)
}
return Result{Vector: response.Data[0].Embedding, ProviderRef: "ark:" + a.model}, nil
}
func Validate(vector []float64) error {
if len(vector) != Dimensions {
return fmt.Errorf("embedding dimensions=%d want=%d", len(vector), Dimensions)
}
for _, value := range vector {
if math.IsNaN(value) || math.IsInf(value, 0) {
return errors.New("embedding contains a non-finite value")
}
}
return nil
}
func Literal(vector []float64) (string, error) {
if err := Validate(vector); err != nil {
return "", err
}
return developmentembedding.Literal(vector), nil
}
@@ -0,0 +1,52 @@
package embeddingprovider
import (
"context"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"time"
)
func TestArkEmbeddingRequestAndResponse(t *testing.T) {
vector := make([]float64, Dimensions)
vector[0] = 0.5
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/api/v3/embeddings" || r.Header.Get("Authorization") != "Bearer test-key" {
t.Fatalf("unexpected embedding request")
}
var body struct {
Model string `json:"model"`
Input string `json:"input"`
Dimensions int `json:"dimensions"`
}
if err := json.NewDecoder(r.Body).Decode(&body); err != nil || body.Model != "embedding-test" || body.Input != "河边小学" || body.Dimensions != Dimensions {
t.Fatalf("body=%+v err=%v", body, err)
}
_ = json.NewEncoder(w).Encode(map[string]any{"data": []any{map[string]any{"index": 0, "embedding": vector}}})
}))
defer server.Close()
provider, err := NewArk(server.URL+"/api/v3", "test-key", "embedding-test", time.Second)
if err != nil {
t.Fatal(err)
}
result, err := provider.Embed(context.Background(), "河边小学")
if err != nil || len(result.Vector) != Dimensions || result.ProviderRef != "ark:embedding-test" || result.Vector[0] != 0.5 {
t.Fatalf("result=%+v err=%v", result, err)
}
}
func TestArkEmbeddingRejectsWrongDimensions(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
_ = json.NewEncoder(w).Encode(map[string]any{"data": []any{map[string]any{"index": 0, "embedding": []float64{1, 2}}}})
}))
defer server.Close()
provider, err := NewArk(server.URL, "test-key", "embedding-test", time.Second)
if err != nil {
t.Fatal(err)
}
if _, err = provider.Embed(context.Background(), "测试"); err == nil {
t.Fatal("wrong vector dimensions were accepted")
}
}