Skip to content

feat: enhance model configuration support #9

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

alexzeitgeist
Copy link

@alexzeitgeist alexzeitgeist commented Jun 29, 2025

Enhanced model configuration support

Overview

Replace simple string-based model lists with a more comprehensive ModelConfig system. This allows fine-grained control over model behavior through per-model configuration of parameters.

FWIW: JetBrains AI Assistant always sends temperature=1.0, which is too high for most non-reasoning models. Which is why I think this configuration is important. 😊

Breaking Changes

  • Model Configuration Format: Model lists in configuration files must now use object format instead of simple strings
    • Before: modelList: ["gpt-4", "gpt-3.5-turbo"]
    • After: modelList: [{ name: "gpt-4" }, { name: "gpt-3.5-turbo" }]

New Features

1. ModelConfig Data Class

Added ModelConfig.kt with support for:

  • name: Model identifier (required)
  • temperature: Override default temperature for specific models
  • extraParameters: Top-level API parameters to include in requests
  • extraBody: Additional parameters to merge into request body

2. Enhanced Parameter Handling

The OpenAI client now processes model configurations:

Supported Extra Parameters:

  • max_tokens: Maximum tokens in response
  • top_p: Nucleus sampling parameter
  • frequency_penalty: Token frequency penalty
  • presence_penalty: Token presence penalty
  • stop: Stop sequences (string or array)
  • seed: Random seed for deterministic output
  • n: Number of completions to generate

Unknown parameters are passed as top-level JSON elements to support provider-specific features.

3. Example Configuration

apiProviders:
  OpenAI:
    type: OpenAi
    baseUrl: https://api.openai.com/v1
    apiKey: sk-proj-[REDACTED]
    modelList:
      - name: gpt-4.1
        temperature: 0.1
      - name: o3
        temperature: 1.0
        extraParameters:
          service_tier: flex
          reasoning_effort: high  # defaults to medium
          # max_completion_tokens: 32768

  Gemini:
    type: Gemini
    apiKey: AIza[REDACTED]
    modelList:
      - name: gemini-2.5-pro
        temperature: 0.3
      - name: gemini-2.5-flash
        temperature: 0.1

  DeepSeek:
    type: DeepSeek
    apiKey: sk-[REDACTED]
    modelList:
      - name: deepseek-chat
        temperature: 0.1
      - name: deepseek-reasoner
        # No temperature override, uses request default

  OpenRouter:
    type: OpenRouter
    apiKey: sk-or-v1-[REDACTED]
    modelList:
      - name: deepseek/deepseek-r1
      - name: x-ai/grok-3-mini
        temperature: 0.1
      - name: x-ai/grok-3
        temperature: 0.1

@Stream29 Stream29 self-requested a review June 29, 2025 17:37
@Stream29
Copy link
Owner

LGTM. I'll review it in several days.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would agree that the idea to support a more detailed configuration is good, but we need backward compatiblility and make most of the configuration things default.

I think a little more hacky way is good: define a custom serializer to accept both plain model name and ModelConfig block.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is too much dumplicate code.

Most of the parameters can be put in the ChatCompletionRequest instance, and we don't need to log for every modification..


suspend fun createStreamingChatCompletion(
baseUrl: String,
apiKey: String,
request: ChatCompletionRequest
request: ChatCompletionRequest,
extraTopLevelParams: Map<String, JsonElement>? = null,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we need a ChatCompletionRequest with more fields, we can just add a nullable property to it.
If we need to add more field into a JSON request, we can just create a Merge<A, B> class and define special serialization strategy for it.


/**
* Convert a string value to the appropriate JsonElement type.
* It tries to parse as a JSON object/array first, then falls back to primitive types.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We know YAML is compatible with JSON. So just let users write YAML in the config and we can transform it into JSON easily.

@Stream29
Copy link
Owner

Stream29 commented Jul 2, 2025

@alexzeitgeist I suggest you to take a look at kaml. This repository uses it to parse YAML config, and we can do some more flexible parsing by hacking its implementation.

For polymorphism serialization, you can refer to kotlinx.serialization.json.JsonContentPolymorphicSerializer.

@Stream29
Copy link
Owner

Stream29 commented Jul 2, 2025

For config format design, I hope it to be like this:

OpenAI:
  type: OpenAi
  baseUrl: ...
  modelList:
    - modelWithSimpleDeclaration
    - modelWithParameter:
        parameterA: value
        parameterB: value
        additionalRequestBody:
          fieldA: value

This may be more natural, with a optional parameter block.

@Stream29
Copy link
Owner

Stream29 commented Jul 2, 2025

I think your idea is great. If you need help, I would like to work with you on this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants