Skip to content

[enhancement] Better AI model name coercion in backend #1327

Open
@KernelDeimos

Description

@KernelDeimos

The goal of this task is to ensure the following:

  • conventional specifiers (ex: openai/gpt-4o-mini) for AI models work
  • lazy specifiers (ex: gpt-4o-mini, groq) work
  • backward-compatibility is preserved

General AI Architecture

For this task it may be helpful to know the general structure of the AI providers. AI providers are actually individual Puter driver implementations, but they register with AIChatService - a parent driver implementation that delegates to each provider.

Image

Coercion in puter.js

The puter.js AI module already does coercion for specific cases, but backend can handle this in a more generalized way which will also ensure that the SDK and API are consistent.

When we call await puter.ai.chat("Hello", { model: 'gpt-4o-mini' }), a request is made to the API that's equivalent to this fetch call:

await fetch('https://api.puter.local/drivers/call', {
    method: 'POST',
    headers: {
        Authorization: `Bearer ${puter.authToken}`,
        'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        interface: 'puter-chat-completion',
        driver: 'openai-completion',
        method: 'complete',
        args: {
            messages: [{ content: 'Hi Hello' }],
            model: 'gpt-4o-mini'
        }
    })
});

The ai-chat driver

Every AI service (openai-completion, xai, groq, openrouter, etc) registers itself as a provider to AIChatService. When all services are initialized (this phase is called consolidation) the AIChatService will register itself as an alias of each AI provider to DriverService so that everything goes through AIChatService as a central controller.

Right now we don't allow calling ai-chat directly because we use the "intended service" (the one that was requested, that ai-chat aliased itself as) to determine which AI provider is handling the request. Part of this task will be to remove this guard and have ai-chat always infer a provider from the model specifier.

Requests that should work but don't work yet

Specifying ai-chat as the driver

await fetch('https://api.puter.local/drivers/call', {
    method: 'POST',
    headers: {
        Authorization: `Bearer ${puter.authToken}`,
        'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        interface: 'puter-chat-completion',
        driver: 'ai-chat',
        method: 'complete',
        args: {
            messages: [{ content: 'Hi Hello' }],
            model: 'gpt-4o-mini'
        }
    })
});

specifying vendor name without supplier name when calling openrouter

await fetch('https://api.puter.local/drivers/call', {
    method: 'POST',
    headers: {
        Authorization: `Bearer ${puter.authToken}`,
        'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        interface: 'puter-chat-completion',
        driver: 'openrouter',
        method: 'complete',
        args: {
            messages: [{ content: 'Hi Hello' }],
            model: 'openai/gpt-4o-mini'
        }
    })
});

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions