docs(models): document oMLX OpenAI-compatible setup
This commit is contained in:
@@ -272,6 +272,8 @@ If `lm-studio` is not explicitly configured, registry adds an implicit discovera
|
||||
|
||||
Runtime discovery fetches models (`GET /models`) and synthesizes model entries with local defaults.
|
||||
|
||||
This path also works for local OpenAI-compatible servers that are not LM Studio. For example, set `LM_STUDIO_BASE_URL=http://127.0.0.1:11434/v1` to discover oMLX through the existing `/v1/models` flow. Do not configure oMLX as `ollama`: Ollama discovery uses native `/api/tags` and `/api/show` endpoints, not OpenAI `/v1/models`.
|
||||
|
||||
### Explicit provider discovery
|
||||
|
||||
You can configure discovery yourself:
|
||||
@@ -606,6 +608,18 @@ providers:
|
||||
name: Qwen 2.5 Coder 32B (local)
|
||||
```
|
||||
|
||||
For oMLX or another local OpenAI-compatible server with a discoverable `/v1/models` endpoint, prefer discovery instead of listing models by hand:
|
||||
|
||||
```yaml
|
||||
providers:
|
||||
omlx:
|
||||
baseUrl: http://127.0.0.1:11434/v1
|
||||
auth: none
|
||||
api: openai-completions
|
||||
discovery:
|
||||
type: openai-models-list
|
||||
```
|
||||
|
||||
### Hosted proxy with env-based key
|
||||
|
||||
```yaml
|
||||
|
||||
@@ -16,13 +16,17 @@ describe("ModelRegistry LM Studio Fixes", () => {
|
||||
tempDir = path.join(os.tmpdir(), `pi-test-lm-studio-fixes-${Snowflake.next()}`);
|
||||
fs.mkdirSync(tempDir, { recursive: true });
|
||||
modelsJsonPath = path.join(tempDir, "models.json");
|
||||
authStorage = await AuthStorage.create(path.join(tempDir, "testauth.db"));
|
||||
authStorage = await AuthStorage.create(":memory:");
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
authStorage.close();
|
||||
if (tempDir && fs.existsSync(tempDir)) {
|
||||
fs.rmSync(tempDir, { recursive: true });
|
||||
try {
|
||||
fs.rmSync(tempDir, { recursive: true, force: true });
|
||||
} catch (error) {
|
||||
if ((error as NodeJS.ErrnoException).code !== "EBUSY") throw error;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -59,4 +63,37 @@ describe("ModelRegistry LM Studio Fixes", () => {
|
||||
expect(available.some(m => m.provider === "ollama")).toBe(true);
|
||||
expect(available.some(m => m.provider === "lm-studio")).toBe(true);
|
||||
});
|
||||
|
||||
test("LM_STUDIO_BASE_URL can target any local OpenAI-compatible /v1 server", async () => {
|
||||
const originalBaseUrl = Bun.env.LM_STUDIO_BASE_URL;
|
||||
Bun.env.LM_STUDIO_BASE_URL = "http://127.0.0.1:11434/v1";
|
||||
let requestedUrl = "";
|
||||
try {
|
||||
const fetchMock: FetchImpl = input => {
|
||||
const url = String(input);
|
||||
if (url.includes(":11434/v1/models")) {
|
||||
requestedUrl = url;
|
||||
return Promise.resolve(
|
||||
new Response(JSON.stringify({ data: [{ id: "omlx-model" }] }), {
|
||||
status: 200,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
}),
|
||||
);
|
||||
}
|
||||
return Promise.resolve(new Response(null, { status: 404 }));
|
||||
};
|
||||
|
||||
const registry = new ModelRegistry(authStorage, modelsJsonPath, { fetch: fetchMock });
|
||||
await registry.refresh();
|
||||
|
||||
expect(requestedUrl).toBe("http://127.0.0.1:11434/v1/models");
|
||||
expect(registry.getAll().some(m => m.provider === "lm-studio" && m.id === "omlx-model")).toBe(true);
|
||||
} finally {
|
||||
if (originalBaseUrl === undefined) {
|
||||
delete Bun.env.LM_STUDIO_BASE_URL;
|
||||
} else {
|
||||
Bun.env.LM_STUDIO_BASE_URL = originalBaseUrl;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user