Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

Make the OpenAI LLM provider adapt to OpenAI-compatible servers and reasoning models

未关闭
#10,570 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

维护者通常 1 天内回复

@MaybeSomeone-arc18 已经在做这个了。

开始于 2026年10月17日。

  • #10636 来自 @MaybeSomeone-arc18 —— 未关闭

评估

难度
4/5
预计耗时
3-5 天
新手友好度
25/100
Issue 类型
重构
描述清晰度
基本清楚
活跃度
活跃
技术栈
python
领域
backend

调研方向

Start in web/pgadmin/llm/providers/openai.py, at _should_use_responses_api (around lines 179-184) and the max_completion_tokens call (line 205), then read client.py around get_llm_client() (line 242). Tests belong in web/pgadmin/llm/tests/test_openai_stream.py, with the Go library's adaptive-parameter scenarios as a reference. Done means the provider adapts token-limit and Responses routing from server errors, caches learned flags per (base_url, model), and handles reasoning-model budgets with bounded retries.

由索引模型根据 Issue 内容生成。

描述

Bug

The OpenAI provider in web/pgadmin/llm/providers/openai.py hard-codes OpenAI's own request conventions, which breaks or degrades it against the OpenAI-compatible servers we tell people to use (LM Studio, LiteLLM, vLLM, EXO, Z.ai's GLM and so on):

  • It always sends max_completion_tokens (line 205), an OpenAI-specific parameter that many compatible servers ignore or reject; they expect max_tokens.
  • It switches to the Responses API (/responses) when an error message happens to contain one of a few substrings (_should_use_responses_api, lines 179-184), including "not a chat model". An unrelated error from a third-party server can therefore move the client onto an endpoint that server doesn't implement, hiding the real failure.
  • Reasoning models can spend the whole output budget thinking, coming back with empty content and finish_reason: length. The report pipeline caps output at 500 tokens for planning and 1500 per section (reports/pipeline.py:221 and :294), and the resulting error from _raise_max_tokens_error blames the request size and suggests a larger context window, which is the wrong diagnosis.

Rather than a subclass per vendor (as proposed in #10216), or a check of the hostname against api.openai.com (which would misclassify Azure OpenAI and gateways in front of OpenAI), I'd like the provider to adapt to whatever it is connected to, learning from the server's own responses. pgedge-go-llm-lib 0.4.0 does this already (pgEdge/pgedge-go-llm-lib#43, llm/provider/openai/adapt.go) and is a good reference, tests included.

Proposed design

Token-limit parameter. Send max_tokens by default, since that is what compatible servers understand. If the server rejects it with a 400 whose JSON error has param == "max_tokens" and code == "unsupported_parameter" (as OpenAI's reasoning models do), retry with max_completion_tokens and remember that. Only OpenAI then pays a failed round trip, and only once per model.

Responses API. Replace the substring heuristic with a check on the structured error: reroute to /responses only on a 400 or 404 with no param and a message saying the model is only supported in v1/responses, and remember that too.

Bounded retries. Apply each adjustment at most once per call, and cap the number of sends per call (the Go library uses three), so a chain such as "rerouted, then a parameter rejected" completes without looping.

Remember what was learned across requests. get_llm_client() (client.py:242) builds a new OpenAIClient for every request, so the existing _use_responses_api flag is lost each time. Keep the learned flags in a module-level dict keyed on (base_url, model); pgAdmin is single-process, so in-memory state is sufficient. Log each adjustment once, at debug level.

Reasoning models. Detect that a model reasons from either signal:

  • usage.completion_tokens_details.reasoning_tokens greater than zero (OpenAI);
  • a reasoning_content field on the message or stream delta (Z.ai's GLM, DeepSeek and others).

Once seen, set a "reasoning" flag in the same cache, and have the client multiply the caller's max_tokens (by three, say), so callers such as the report pipeline need no changes. The caps are ceilings, so this costs nothing unless the model uses the extra tokens. On empty content with finish_reason: length, retry once with the larger budget and set the flag, rather than failing straight away; if it is still empty, raise an error that says the output budget was exhausted, not that the request was too large.

Two points to settle during implementation, by testing against real reasoning models: whether three times is enough (GLM-4.7 always thinks, and Z.ai's docs don't say whether reasoning counts against max_tokens), and whether the 500-token planning cap should be raised regardless.

Docker Model Runner. providers/docker.py is a separate 592-line client for what is an OpenAI-compatible API, and also hard-codes max_completion_tokens (line 140). Once the above is in place, it could become a thin subclass that keeps its loopback-only URL validation. This can be a follow-up.

Tidy-ups in the same area. is_available() uses startswith against the default URL (line 100), which also matches a host such as api.openai.com.example.net; compare hostnames instead.

Tests

Port the Go library's adaptive-parameter scenarios into web/pgadmin/llm/tests/test_openai_stream.py, covering both the non-streaming and streaming paths: which token-limit key is sent first and after a rejection; that a custom host never reroutes to /responses on an unrelated error; that learned state survives a new client for the same URL and model; the retry cap; and the reasoning detection and budget scaling, including the empty-response retry.

Documentation

Update the OpenAI-compatible provider lists in docs/en_US/ai_tools.rst and docs/en_US/preferences.rst to include GLM (Z.ai), and say that any non-default host must be added to ALLOWED_LLM_API_URLS by an administrator before pgAdmin will connect to it.

Thanks to @shawonis08, whose work on #10216 diagnosed the underlying problems.

主要语言
Python
星标
3.9k
派生
910
平均合并
1 天 16 小时
30 天内合并 PR
41

环境准备

  • 提供 Dockerfile 或 Docker Compose 文件
  • 没有 Pull Request 模板
  • 阅读贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

pgadmin-org/pgadmin4 的其他 Issue

查看 pgadmin-org/pgadmin4 的全部 Issue

相似的 Issue

更多 Python Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。