# How to Configure Custom API Endpoints and Models for Different LLM Providers in Prompt‑Optimizer

> Learn to configure custom API endpoints and models for various LLM providers in Prompt-Optimizer using its provider registry system. Easily override settings via UI or programmatically.

- Repository: [且炼时光/prompt-optimizer](https://github.com/linshenkx/prompt-optimizer)
- Tags: how-to-guide
- Published: 2026-02-23

---

**Prompt‑Optimizer uses a provider registry system where each LLM defines a `defaultBaseURL` and `connectionSchema`, allowing you to override endpoints and models via the UI or programmatically through the `TextAdapterRegistry`.**

Prompt‑Optimizer is an open‑source tool designed to refine and optimize prompts across multiple large language models. To support diverse deployment scenarios—from cloud APIs to self‑hosted instances—the codebase provides a flexible architecture to configure custom API endpoints and models for different LLM providers in prompt‑optimizer.

## Understanding the Provider Registry Architecture

The core abstraction is the **provider registry** located in [`packages/core/src/services/model/defaults.ts`](https://github.com/linshenkx/prompt-optimizer/blob/main/packages/core/src/services/model/defaults.ts). Every supported LLM is defined as a `TextProvider` object containing:

- **`id`** – the unique registry key (e.g., `openai`, `gemini`, `anthropic`).
- **`defaultBaseURL`** – the canonical endpoint used when no custom URL is provided.
- **`connectionSchema`** – a schema object declaring required fields (typically `apiKey`) and optional overrides (`baseURL`, `model`).

For example, OpenAI’s default configuration is declared as:

```typescript
// packages/core/src/services/model/defaults.ts
{
  id: 'openai',
  name: 'OpenAI',
  defaultBaseURL: 'https://api.openai.com/v1',
  connectionSchema: {
    required: ['apiKey'],
    optional: ['baseURL', 'model']
  }
}

```

## Overriding Endpoints in the Connection Config UI

The front‑end exposes a **Connection Config** dialog implemented in [`packages/ui/src/composables/model/useConnectionConfig.ts`](https://github.com/linshenkx/prompt-optimizer/blob/main/packages/ui/src/composables/model/useConnectionConfig.ts). When you select a provider, the composable auto‑populates the **Base URL** field with the provider’s `defaultBaseURL`:

```typescript
// packages/ui/src/composables/model/useConnectionConfig.ts
if (providerMeta?.defaultBaseURL && !currentConfig?.baseURL) {
  result.baseURL = providerMeta.defaultBaseURL
}

```

You can overwrite this value to point at a custom endpoint—such as a self‑hosted **OpenAI‑compatible** server or a proxy. The **Model selector** ([`useTextModelManager.ts`](https://github.com/linshenkx/prompt-optimizer/blob/main/useTextModelManager.ts)) then queries the effective endpoint to retrieve available models, ensuring that custom models exposed by your endpoint appear in the dropdown.

## Programmatically Adding Custom Providers

To add a provider that is not built‑in, extend the registry and register it at runtime.

### Step 1: Define Provider Metadata

Create a new `TextProvider` object in [`packages/core/src/services/model/defaults.ts`](https://github.com/linshenkx/prompt-optimizer/blob/main/packages/core/src/services/model/defaults.ts) or a custom extension file:

```typescript
export const customProvider: TextProvider = {
  id: 'my-custom-llm',
  name: 'My Custom LLM',
  defaultBaseURL: 'https://api.mycustomllm.com/v1',
  connectionSchema: {
    required: ['apiKey'],
    optional: ['baseURL', 'model'],
    fieldTypes: { apiKey: 'string', baseURL: 'string', model: 'string' }
  },
  staticModels: [{ id: 'my-model-1', name: 'My Model 1' }]
}

```

### Step 2: Register the Provider

Import the registry and register the provider during application initialization:

```typescript
import { TextAdapterRegistry } from '@/services/llm/adapters/registry'
import { customProvider } from '@/services/model/defaults'

TextAdapterRegistry.getInstance().register(customProvider)

```

Once registered, the provider appears in the UI automatically because [`useTextModelManager.ts`](https://github.com/linshenkx/prompt-optimizer/blob/main/useTextModelManager.ts) pulls the full list via:

```typescript
providers.value = textAdapterRegistry?.getAllProviders?.() || []

```

## Runtime Resolution Flow

Understanding how the configuration flows at runtime ensures you can debug connection issues effectively.

| Step | Component | Action |
|------|-----------|--------|
| 1 | **Provider Registry** ([`defaults.ts`](https://github.com/linshenkx/prompt-optimizer/blob/main/defaults.ts)) | Supplies `defaultBaseURL` and `connectionSchema`. |
| 2 | **UI Config** ([`useConnectionConfig.ts`](https://github.com/linshenkx/prompt-optimizer/blob/main/useConnectionConfig.ts)) | Displays default URL; accepts user override. |
| 3 | **Adapter** ([`openai-adapter.ts`](https://github.com/linshenkx/prompt-optimizer/blob/main/openai-adapter.ts), [`gemini-adapter.ts`](https://github.com/linshenkx/prompt-optimizer/blob/main/gemini-adapter.ts)) | Resolves effective URL: `config.baseURL \|\| provider.defaultBaseURL`. |
| 4 | **LLM Service** ([`llm/service.ts`](https://github.com/linshenkx/prompt-optimizer/blob/main/llm/service.ts)) | Sends HTTP requests to the resolved endpoint. |
| 5 | **Model Manager** ([`useTextModelManager.ts`](https://github.com/linshenkx/prompt-optimizer/blob/main/useTextModelManager.ts)) | Fetches model list from the effective endpoint. |

For example, in the OpenAI adapter ([`packages/core/src/services/llm/adapters/openai-adapter.ts`](https://github.com/linshenkx/prompt-optimizer/blob/main/packages/core/src/services/llm/adapters/openai-adapter.ts)), the request URL is constructed as:

```typescript
const baseURL = config.connectionConfig.baseURL || this.getProvider().defaultBaseURL
http.post(`${baseURL}${config.endpoints.chat}`, …)

```

## Code Examples

### Using a Custom Endpoint in a Test Script

```typescript
import { createLLMService } from '@/services/llm/service'

const service = createLLMService({
  providerId: 'openai',
  connectionConfig: { 
    apiKey: 'sk-test-key', 
    baseURL: 'https://my-proxy.example.com/v1' 
  }
})

await service.chat({ 
  model: 'gpt-4o', 
  messages: [{ role: 'user', content: 'Hello' }] 
})

```

### Extending the Connection Schema for a Corporate Proxy

```typescript
// packages/core/src/services/model/defaults.ts
export const corporateOpenAI: TextProvider = {
  id: 'corporate-openai',
  name: 'Corporate OpenAI Gateway',
  defaultBaseURL: 'https://gateway.corp.net/openai/v1',
  connectionSchema: {
    required: ['apiKey', 'workspaceId'],
    optional: ['baseURL', 'model'],
    fieldTypes: { 
      apiKey: 'string', 
      workspaceId: 'string',
      baseURL: 'string', 
      model: 'string' 
    }
  }
}

```

## Key Files

| File | Role | Link |
|------|------|------|
| [`packages/core/src/services/model/defaults.ts`](https://github.com/linshenkx/prompt-optimizer/blob/main/packages/core/src/services/model/defaults.ts) | Provider default URLs and static model data | https://github.com/linshenkx/prompt-optimizer/blob/develop/packages/core/src/services/model/defaults.ts |
| [`packages/core/src/services/llm/adapters/openai-adapter.ts`](https://github.com/linshenkx/prompt-optimizer/blob/main/packages/core/src/services/llm/adapters/openai-adapter.ts) | Resolves effective `baseURL` and builds request URLs for OpenAI | https://github.com/linshenkx/prompt-optimizer/blob/develop/packages/core/src/services/llm/adapters/openai-adapter.ts |
| [`packages/core/src/services/llm/adapters/gemini-adapter.ts`](https://github.com/linshenkx/prompt-optimizer/blob/main/packages/core/src/services/llm/adapters/gemini-adapter.ts) | Same pattern for Google Gemini | https://github.com/linshenkx/prompt-optimizer/blob/develop/packages/core/src/services/llm/adapters/gemini-adapter.ts |
| [`packages/ui/src/composables/model/useConnectionConfig.ts`](https://github.com/linshenkx/prompt-optimizer/blob/main/packages/ui/src/composables/model/useConnectionConfig.ts) | UI logic that injects provider defaults and allows overrides | https://github.com/linshenkx/prompt-optimizer/blob/develop/packages/ui/src/composables/model/useConnectionConfig.ts |
| [`packages/ui/src/composables/model/useTextModelManager.ts`](https://github.com/linshenkx/prompt-optimizer/blob/main/packages/ui/src/composables/model/useTextModelManager.ts) | Retrieves provider list and model metadata for selection UI | https://github.com/linshenkx/prompt-optimizer/blob/develop/packages/ui/src/composables/model/useTextModelManager.ts |
| [`packages/core/src/services/adapters/abstract-registry.ts`](https://github.com/linshenkx/prompt-optimizer/blob/main/packages/core/src/services/adapters/abstract-registry.ts) | Base class for provider registration (both text and image) | https://github.com/linshenkx/prompt-optimizer/blob/develop/packages/core/src/services/adapters/abstract-registry.ts |
| [`packages/core/src/services/llm/service.ts`](https://github.com/linshenkx/prompt-optimizer/blob/main/packages/core/src/services/llm/service.ts) | Core LLM service that consumes the resolved configuration | https://github.com/linshenkx/prompt-optimizer/blob/develop/packages/core/src/services/llm/service.ts |

## Summary

- **Provider Registry**: Each LLM is defined in [`packages/core/src/services/model/defaults.ts`](https://github.com/linshenkx/prompt-optimizer/blob/main/packages/core/src/services/model/defaults.ts) with a `defaultBaseURL` and `connectionSchema`.
- **UI Override**: The connection dialog ([`useConnectionConfig.ts`](https://github.com/linshenkx/prompt-optimizer/blob/main/useConnectionConfig.ts)) pre-fills the default endpoint but allows you to specify custom URLs for proxies or self-hosted instances.
- **Adapter Resolution**: At runtime, adapters like [`openai-adapter.ts`](https://github.com/linshenkx/prompt-optimizer/blob/main/openai-adapter.ts) resolve the effective URL using `config.baseURL || provider.defaultBaseURL`.
- **Extensibility**: You can register new providers via `TextAdapterRegistry.register()` without modifying core UI code, and the model manager will automatically surface them.

## Frequently Asked Questions

### How do I point Prompt‑Optimizer to a self‑hosted OpenAI‑compatible server?

Enter your custom endpoint in the **Base URL** field of the Connection Config dialog. The UI pre-fills the standard OpenAI URL (`https://api.openai.com/v1`), but you can overwrite it with your local address (e.g., `http://localhost:8000/v1`). The [`openai-adapter.ts`](https://github.com/linshenkx/prompt-optimizer/blob/main/openai-adapter.ts) will then route all requests to your server instead of the official API.

### Can I add a completely new LLM provider that isn't built‑in?

Yes. Define a new `TextProvider` object in [`packages/core/src/services/model/defaults.ts`](https://github.com/linshenkx/prompt-optimizer/blob/main/packages/core/src/services/model/defaults.ts) with a unique `id`, `defaultBaseURL`, and `connectionSchema`. Then register it at runtime using `TextAdapterRegistry.getInstance().register(customProvider)`. The UI automatically picks up the new provider via [`useTextModelManager.ts`](https://github.com/linshenkx/prompt-optimizer/blob/main/useTextModelManager.ts), which calls `getAllProviders()`.

### Where does the UI get the default API endpoint for each provider?

The default endpoints are defined in the **provider metadata** within [`packages/core/src/services/model/defaults.ts`](https://github.com/linshenkx/prompt-optimizer/blob/main/packages/core/src/services/model/defaults.ts). When you select a provider in the UI, [`useConnectionConfig.ts`](https://github.com/linshenkx/prompt-optimizer/blob/main/useConnectionConfig.ts) reads the `defaultBaseURL` property and injects it into the form. If the field is left empty by the user, the system falls back to this default at request time.

### What happens if I leave the Base URL field empty in the connection settings?

If the field is empty, the LLM adapter uses the provider’s `defaultBaseURL` defined in [`defaults.ts`](https://github.com/linshenkx/prompt-optimizer/blob/main/defaults.ts). For example, [`openai-adapter.ts`](https://github.com/linshenkx/prompt-optimizer/blob/main/openai-adapter.ts) resolves the effective URL with `config.connectionConfig.baseURL || this.getProvider().defaultBaseURL`. This ensures the official endpoint is used as a safe fallback while still allowing custom overrides when needed.