This commit is contained in:
@@ -25,6 +25,13 @@ type OpenAICompatibleLocalAdapter struct {
|
||||
apiKey string
|
||||
}
|
||||
|
||||
// compatibleDefaultContextBytes is a conservative bound used when an
|
||||
// OpenAI-compatible local endpoint omits n_ctx from /v1/models. The adapter
|
||||
// is a chat-completions adapter, so advisory capability is known from the
|
||||
// adapter contract; quality and activation still require governed
|
||||
// qualification/evaluation in the capability registry.
|
||||
const compatibleDefaultContextBytes int64 = 32 << 10
|
||||
|
||||
func NewOpenAICompatibleLocalAdapter(raw string, transport http.RoundTripper) (*OpenAICompatibleLocalAdapter, error) {
|
||||
return NewOpenAICompatibleLocalAdapterWithAPIKey(raw, "", transport)
|
||||
}
|
||||
@@ -90,7 +97,10 @@ func (a *OpenAICompatibleLocalAdapter) Discover(ctx context.Context) ([]Discover
|
||||
stableMetadata := fmt.Sprintf("%s\x00%s\x00%d\x00%d\x00%d\x00%d\x00%s", item.ID, item.OwnedBy, item.Meta.Context, item.Meta.TrainingContext, item.Meta.Parameters, item.Meta.Size, item.Meta.FileType)
|
||||
digest := sha256.Sum256([]byte(stableMetadata))
|
||||
contextBytes := item.Meta.Context * 4
|
||||
models = append(models, DiscoveredModel{ProviderModelID: capability.ProviderModelID(item.ID), Fingerprint: capability.ModelFingerprint(hex.EncodeToString(digest[:])), MaxContextBytes: contextBytes, Modalities: []capability.ModelModality{capability.ModalityText}, Capabilities: []capability.ModelCapability{capability.CapabilityUnknown}, SizeBytes: item.Meta.Size, Runtime: item.OwnedBy, Quantization: item.Meta.FileType})
|
||||
if contextBytes <= 0 {
|
||||
contextBytes = compatibleDefaultContextBytes
|
||||
}
|
||||
models = append(models, DiscoveredModel{ProviderModelID: capability.ProviderModelID(item.ID), Fingerprint: capability.ModelFingerprint(hex.EncodeToString(digest[:])), MaxContextBytes: contextBytes, Modalities: []capability.ModelModality{capability.ModalityText}, Capabilities: []capability.ModelCapability{capability.CapabilityAdvisory}, SizeBytes: item.Meta.Size, Runtime: item.OwnedBy, Quantization: item.Meta.FileType})
|
||||
}
|
||||
return models, ProviderProbe{Health: capability.HealthAvailable}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,34 @@ type captureRoundTripper struct {
|
||||
body []byte
|
||||
}
|
||||
|
||||
type modelsMetadataRoundTripper struct{}
|
||||
|
||||
func (modelsMetadataRoundTripper) RoundTrip(request *http.Request) (*http.Response, error) {
|
||||
return &http.Response{
|
||||
StatusCode: http.StatusOK,
|
||||
Body: io.NopCloser(strings.NewReader(`{"data":[{"id":"medium-model","owned_by":"llama.cpp","meta":{}}]}`)),
|
||||
Header: make(http.Header),
|
||||
Request: request,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func TestOpenAICompatibleLocalAdapterNormalizesMinimalModelMetadata(t *testing.T) {
|
||||
adapter, err := NewOpenAICompatibleLocalAdapter("http://gateway/v1", modelsMetadataRoundTripper{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
models, probe := adapter.Discover(context.Background())
|
||||
if probe.Health != capability.HealthAvailable || len(models) != 1 {
|
||||
t.Fatalf("unexpected discovery result: probe=%+v models=%+v", probe, models)
|
||||
}
|
||||
if models[0].MaxContextBytes != compatibleDefaultContextBytes {
|
||||
t.Fatalf("context bound=%d, want %d", models[0].MaxContextBytes, compatibleDefaultContextBytes)
|
||||
}
|
||||
if len(models[0].Capabilities) != 1 || models[0].Capabilities[0] != capability.CapabilityAdvisory {
|
||||
t.Fatalf("capabilities=%v, want advisory", models[0].Capabilities)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOpenAICompatibleLocalAdapterUsesConfiguredTimeout(t *testing.T) {
|
||||
adapter, err := NewOpenAICompatibleLocalAdapterWithAPIKeyAndTimeout("http://gateway/v1", "", &captureRoundTripper{}, 47*time.Second)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user