Skip to content

Commit 5b477f7

Browse files
committed
Expand model fit runtime capability detection
1 parent f91eec6 commit 5b477f7

8 files changed

Lines changed: 1229 additions & 160 deletions

File tree

forge-go/api/modelfit.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,22 @@ func (s *Server) handleListLocalModelFits() http.HandlerFunc {
5959
}
6060
}
6161

62+
func (s *Server) handleGetModelFitCapabilities() http.HandlerFunc {
63+
return func(w http.ResponseWriter, r *http.Request) {
64+
svc := s.modelFit
65+
if svc == nil {
66+
svc = newModelFitService(forgepath.LocalModelCatalogPath(), forgepath.DependencyConfigPath(), modelfit.DefaultProfiler{})
67+
}
68+
69+
system, err := svc.profiler.Profile(r.Context())
70+
if err != nil {
71+
ReplyError(w, http.StatusInternalServerError, err.Error())
72+
return
73+
}
74+
ReplyJSON(w, http.StatusOK, system)
75+
}
76+
}
77+
6278
func parseBoolQuery(raw string) bool {
6379
switch strings.TrimSpace(strings.ToLower(raw)) {
6480
case "1", "true", "yes", "y", "on":

forge-go/api/modelfit_test.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,54 @@ func TestRusticModelFitRouteRejectsInvalidLimit(t *testing.T) {
115115
require.Equal(t, http.StatusBadRequest, rr.Code)
116116
require.Contains(t, rr.Body.String(), "invalid limit")
117117
}
118+
119+
func TestRusticModelFitCapabilitiesRouteReturnsSystemProfile(t *testing.T) {
120+
t.Setenv("FORGE_ENABLE_PUBLIC_API", "false")
121+
t.Setenv("FORGE_ENABLE_UI_API", "true")
122+
t.Setenv("FORGE_IDENTITY_MODE", "local")
123+
t.Setenv("FORGE_QUOTA_MODE", "local")
124+
125+
s := NewServer(nil, nil, nil, nil, nil, ":0").WithModelFit(
126+
"",
127+
"",
128+
staticProfiler{profile: modelfit.SystemProfile{
129+
TotalRAMBytes: 32 * 1024 * 1024 * 1024,
130+
AvailableRAMBytes: 24 * 1024 * 1024 * 1024,
131+
CPUCores: 12,
132+
Backend: modelfit.BackendCUDA,
133+
RuntimeUsableAcceleration: true,
134+
SelectedAcceleratorID: "nvidia-0",
135+
Confidence: modelfit.DetectionConfidenceProbe,
136+
ReasonCodes: []modelfit.DiagnosticReason{modelfit.ReasonRuntimeDeviceDetected},
137+
Runtime: modelfit.RuntimeCapabilityProfile{
138+
RuntimeAvailable: true,
139+
SelectedBackend: modelfit.BackendCUDA,
140+
Confidence: modelfit.DetectionConfidenceProbe,
141+
UsableAccelerators: []modelfit.UsableAccelerator{
142+
{
143+
ID: "nvidia-0",
144+
Vendor: "nvidia",
145+
Name: "RTX 4090",
146+
Backend: modelfit.BackendCUDA,
147+
Discrete: true,
148+
TotalMemoryBytes: 24 * 1024 * 1024 * 1024,
149+
},
150+
},
151+
},
152+
}},
153+
)
154+
router := s.buildRouter()
155+
156+
req := httptest.NewRequest(http.MethodGet, "/rustic/modelfit/capabilities", nil)
157+
rr := httptest.NewRecorder()
158+
router.ServeHTTP(rr, req)
159+
require.Equal(t, http.StatusOK, rr.Code)
160+
161+
var system modelfit.SystemProfile
162+
require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &system))
163+
require.True(t, system.RuntimeUsableAcceleration)
164+
require.Equal(t, modelfit.BackendCUDA, system.Backend)
165+
require.Equal(t, "nvidia-0", system.SelectedAcceleratorID)
166+
require.Contains(t, system.ReasonCodes, modelfit.ReasonRuntimeDeviceDetected)
167+
require.Len(t, system.Runtime.UsableAccelerators, 1)
168+
}

forge-go/api/server.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ func (s *Server) buildRouter() *gin.Engine {
152152
if enableUI {
153153
s.registerRusticUIRoutes(router, gemGen)
154154
router.GET("/rustic/modelfit/local-models", wrapHTTP(s.handleListLocalModelFits()))
155+
router.GET("/rustic/modelfit/capabilities", wrapHTTP(s.handleGetModelFitCapabilities()))
155156
router.GET("/rustic/observe/guilds/:guild_id/messages/:msg_id/spans", wrapHTTPWithPathValues(s.handleObserveMessageSpans(), "guild_id", "msg_id"))
156157
router.GET("/rustic/catalog/blueprints/:blueprint_id/dependencies", wrapHTTPWithPathValues(handleGetBlueprintDependencies(s.store), "blueprint_id"))
157158
router.GET("/rustic/dependencies", wrapHTTP(handleListConfiguredDependencies()))

0 commit comments

Comments
 (0)