Skip to content

Commit e93a023

Browse files
authored
Merge pull request #540 from docker/responses
Add OpenAI Responses API compatibility layer
2 parents c6e9171 + 2fa8cc1 commit e93a023

File tree

11 files changed

+3309
-5
lines changed

11 files changed

+3309
-5
lines changed

main.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/docker/model-runner/pkg/metrics"
2424
"github.com/docker/model-runner/pkg/middleware"
2525
"github.com/docker/model-runner/pkg/ollama"
26+
"github.com/docker/model-runner/pkg/responses"
2627
"github.com/docker/model-runner/pkg/routing"
2728
"github.com/sirupsen/logrus"
2829
)
@@ -165,6 +166,16 @@ func main() {
165166
router.Handle(inference.ModelsPrefix, modelHandler)
166167
router.Handle(inference.ModelsPrefix+"/", modelHandler)
167168
router.Handle(inference.InferencePrefix+"/", schedulerHTTP)
169+
// Add OpenAI Responses API compatibility layer
170+
responsesHandler := responses.NewHTTPHandler(log, schedulerHTTP, nil)
171+
router.Handle(responses.APIPrefix+"/", responsesHandler)
172+
router.Handle(responses.APIPrefix, responsesHandler) // Also register for exact match without trailing slash
173+
router.Handle("/v1"+responses.APIPrefix+"/", responsesHandler)
174+
router.Handle("/v1"+responses.APIPrefix, responsesHandler)
175+
// Also register Responses API under inference prefix to support all inference engines
176+
router.Handle(inference.InferencePrefix+responses.APIPrefix+"/", responsesHandler)
177+
router.Handle(inference.InferencePrefix+responses.APIPrefix, responsesHandler)
178+
168179
// Add path aliases: /v1 -> /engines/v1, /rerank -> /engines/rerank, /score -> /engines/score.
169180
aliasHandler := &middleware.AliasHandler{Handler: schedulerHTTP}
170181
router.Handle("/v1/", aliasHandler)

pkg/inference/models/adapter.go

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package models
22

33
import (
4+
"encoding/json"
45
"fmt"
56

67
"github.com/docker/model-runner/pkg/distribution/types"
@@ -27,12 +28,23 @@ func ToModel(m types.Model) (*Model, error) {
2728
created = desc.Created.Unix()
2829
}
2930

30-
return &Model{
31+
model := &Model{
3132
ID: id,
3233
Tags: m.Tags(),
3334
Created: created,
3435
Config: cfg,
35-
}, nil
36+
}
37+
38+
// Marshal the config to populate RawConfig
39+
if cfg != nil {
40+
configData, err := json.Marshal(cfg)
41+
if err != nil {
42+
return nil, fmt.Errorf("marshal config: %w", err)
43+
}
44+
model.RawConfig = configData
45+
}
46+
47+
return model, nil
3648
}
3749

3850
// ToModelFromArtifact converts a types.ModelArtifact (typically from remote registry)
@@ -58,10 +70,21 @@ func ToModelFromArtifact(artifact types.ModelArtifact) (*Model, error) {
5870
created = desc.Created.Unix()
5971
}
6072

61-
return &Model{
73+
model := &Model{
6274
ID: id,
6375
Tags: nil, // Remote models don't have local tags
6476
Created: created,
6577
Config: cfg,
66-
}, nil
78+
}
79+
80+
// Marshal the config to populate RawConfig
81+
if cfg != nil {
82+
configData, err := json.Marshal(cfg)
83+
if err != nil {
84+
return nil, fmt.Errorf("marshal config: %w", err)
85+
}
86+
model.RawConfig = configData
87+
}
88+
89+
return model, nil
6790
}

pkg/inference/models/api.go

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,35 @@ type Model struct {
112112
Created int64 `json:"created"`
113113
// Config describes the model. Can be either Docker format (*types.Config)
114114
// or ModelPack format (*modelpack.Model).
115-
Config types.ModelConfig `json:"config"`
115+
Config types.ModelConfig `json:"-"`
116+
// RawConfig is used for JSON marshaling/unmarshaling
117+
RawConfig json.RawMessage `json:"config"`
118+
}
119+
120+
// MarshalJSON implements custom marshaling for Model
121+
func (m Model) MarshalJSON() ([]byte, error) {
122+
// Define a temporary struct to avoid recursion
123+
type Alias Model
124+
aux := struct {
125+
*Alias
126+
RawConfig json.RawMessage `json:"config"`
127+
}{
128+
Alias: (*Alias)(&m),
129+
}
130+
131+
// Marshal the config separately
132+
if m.Config != nil {
133+
configData, err := json.Marshal(m.Config)
134+
if err != nil {
135+
return nil, err
136+
}
137+
aux.RawConfig = configData
138+
} else {
139+
// If Config is nil, use the RawConfig if available
140+
aux.RawConfig = m.RawConfig
141+
}
142+
143+
return json.Marshal(aux)
116144
}
117145

118146
// UnmarshalJSON implements custom JSON unmarshaling for Model.

0 commit comments

Comments
 (0)