xyy45 opened a new issue, #4391:
URL: https://github.com/apache/hertzbeat/issues/4391

   ### Is there an existing issue for this?
   
   - [x] I have searched the existing issues
   
   ### Current Behavior
   
   Two related things in `hertzbeat-ai` that make non-OpenAI providers awkward 
to set up. Both are on
   current `master` (2.0-SNAPSHOT). I ran the app against a local recording 
proxy to see what it
   actually sends rather than guessing from the code.
   
   **1. `temperature` is fixed in code.**
   
   `hertzbeat-ai/.../config/LlmConfig.java:104-109` builds the options with 
`.temperature(0.3)`, and
   `ModelProviderConfig` 
(`hertzbeat-common-core/.../entity/dto/ModelProviderConfig.java:33-54`) only
   has `type / code / baseUrl / model / apiKey / participationModel`, so there 
is no way to change or
   drop it. This is the body the proxy recorded, with message contents and tool 
schemas left out:
   
   ```json
   {
     "model": "deepseek-reasoner",
     "temperature": 0.3,
     "stream": true,
     "stream_options": { "include_usage": true },
     "tools": [ "..." ],
     "messages": [ "..." ]
   }
   ```
   
   Those six keys are all that goes out. `top_p`, `n`, `tool_choice`, 
`response_format` and
   `max_tokens` are not sent. So the one generation parameter that does get 
sent is the one a model is
   most likely to disagree about, and an operator cannot touch it.
   
   **2. `baseUrl` and `model` are filled in from a hardcoded list of `code` 
values.**
   
   `LlmConfig.java:79-101`: when `baseUrl` is empty it is chosen by `code`, and 
the `else` branch sets
   `https://api.openai.com/v1`. `model` works the same way and falls through to 
`gpt-5` (I read that
   off the source, I could not confirm it on the wire since the request is 
rejected before the model is
   checked). Nothing is logged about the fallthrough, so all you get back is an 
error from a host you
   never configured.
   
   ### Expected Behavior
   
   Generation parameters that are fixed in code today should be settable per 
provider, and left out of
   the request when not set. I am not saying `0.3` is the wrong default, it 
should stay the default,
   this is only about making it overridable.
   
   A `code` the backend does not know should fail or at least warn, instead of 
quietly inheriting
   OpenAI's endpoint.
   
   ### Steps To Reproduce
   
   1. `POST /api/config/provider` with 
`{"type":"provider","code":"deepseek","apiKey":"sk-invalid","participationModel":"PROTECTED"}`,
 leave `baseUrl` empty
   2. `POST /api/chat/stream` with `{"message":"hi"}` - the error comes back 
from `api.openai.com`, see logs below
   3. For the temperature part, point any provider `baseUrl` at a local 
listener and send one chat
      message; the outbound body carries `temperature` regardless of provider 
or model
   
   ### Environment
   
   - Version: 2.0-SNAPSHOT (master)
   - Module: hertzbeat-ai
   - OS: macOS, JDK 25, embedded H2
   
   ### Debug logs
   
   The key was a throwaway value, so the reply below is the vendor's own masked 
text. Note the host in
   the OkHttp thread name, and that `LlmConfig` only logs bean lifecycle at 
that moment:
   
   ```
   2026-09-21 09:43:59 [http-nio-1157-exec-1] INFO  
org.apache.hertzbeat.ai.config.LlmConfig - Provider configuration change event 
received, refreshing ChatClient bean
   2026-09-21 09:44:17 [OkHttp https://api.openai.com/...] ERROR 
org.springframework.ai.chat.model.MessageAggregator - Aggregation Error
   java.util.concurrent.CompletionException: 
com.openai.errors.UnauthorizedException: 401: Incorrect API key provided: 
sk-fake-***********nope. You can find your API key at 
https://platform.openai.com/account/api-keys.
        at 
com.openai.core.http.RetryingHttpClient.executeAsync$executeWithRetries$lambda$1(RetryingHttpClient.kt:127)
        at 
org.springframework.ai.openai.http.okhttp.SpringAiOpenAiHttpClient$1.onResponse(SpringAiOpenAiHttpClient.java:137)
   ```
   
   It also reaches the chat client as-is:
   
   ```
   event:error
   data:{"conversationId":4,"response":"An error occurred: 
com.openai.errors.UnauthorizedException: 401: Incorrect API key provided: 
sk-fake-***********nope. You can find your API key at 
https://platform.openai.com/account/api-keys.","userMessageId":5,"assistantMessageId":null}
   ```
   
   ### Anything else?
   
   On how far this reaches: the UI cannot produce case 2, since
   `web-app/src/app/pojo/ModelProviderConfig.ts:37-56` only offers `openai` / 
`zai` / `zhipu` in the
   dropdown and fills in a `baseUrl` for them. Case 2 needs `POST 
/api/config/provider`, which accepts
   any `code` string without checking it. Case 1 does affect anyone using the 
UI.
   
   This is not the cause of #3971 and I am not proposing a fix for it here. 
That reporter did set
   `https://api.deepseek.com/v1`, so the empty-`baseUrl` branch is never 
entered, and I have not
   reproduced their 400 myself.
   
   I'd like to work on this. What I have in mind is an optional parameter field 
on `ModelProviderConfig`
   plus the matching change in `LlmConfig`, a warn when `code` is unknown, and 
unit tests for
   `LlmConfig`, which has none today. No new provider names hardcoded. Say the 
word if you would rather
   see it done differently and I'll adjust before opening the PR.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: 
[email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to