## What
This pull request adds **MWS GPT Model Hub** as a built-in model
provider in RAGFlow.
The integration allows users to configure an MWS project endpoint and
token, discover the models available to that project, and use supported
MWS models for chat completion, embeddings, and reranking.
Co-authored-by: ilarionov_n <ilarionov_n@promis.ru>
Re-materialize wiki page graph from merged wiki_page rows after each
batch merge. Adds ProjectWikiGraph/DropWikiGraph, full page_type/slug
identity, delete-then-insert, tests.
## Summary
- Add embedding batch-size metadata to model responses and tenant
overrides.
- Validate embedding dimensions and batch limits across provider
verification and embedding requests.
- Expand validation tests for defaults, limits, and missing metadata.
---------
Signed-off-by: Jin Hai <haijin.chn@gmail.com>
Co-authored-by: Jin Hai <haijin.chn@gmail.com>
Ports dataset knowledge compilation (wiki/graph/tree/mindmap) to the Go
scheduler with a status contract, aligns wiki storage/retrieval with
Python, sizes prompts by content_length, and resolves embedding batch
size from provider capability.
Ports the dataset knowledge compilation (wiki/graph/tree/mindmap) to the
Go scheduler with a status contract, aligns wiki storage/retrieval with
Python, and sizes prompts by content_length.
## Summary
The generic `buildRequestBody` in `internal/entity/models/base_model.go`
unconditionally forwarded `ChatConfig.MaxTokens` as `"max_tokens"` for
every OpenAI-compatible provider.
Providers that need a different token field already delete or override
it after the call (e.g. Xiaomi uses `max_completion_tokens`, Replicate
uses `max_new_tokens`). This change stops setting `max_tokens` in the
shared builder so it only forwards the parameters common across
providers, and each provider remains free to set its own token limit
field.
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
## Summary
Update `conf/all_models.json`: replace legacy `max_tokens` with
`content_length` + `max_output` for all 2,178 chat/vision models, with
values verified against official vendor documentation.
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
## Summary
- Verify and populate `content_length` (context window) and `max_output`
(max generation tokens) for all **478 chat/vision models** across **47
provider configs**
- Data sourced from **official API documentation** via 12 parallel
agents + targeted web verification
- Update Go test assertions to match verified values
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Relate to #17284.
## Summary
Batch 5/6 migrated the rest of the Go model drivers onto the shared HTTP
helpers (`doRequest`, `doStreamRequest`, `applyAuth`). This PR completes
the batch for the remaining OpenAI-compatible chat-streaming drivers
that were still hand-writing HTTP requests:
- **7 drop-in migrations**: deepseek, gpustack, groq, longcat, moonshot,
openai, siliconflow
- **1 adapter migration**: minimax (relocated its `io.Pipe`
error-interception into the `doStreamRequest` handler)
- **1 full migration**: azure_openai (all four paths: chat, streaming,
embeddings, list-models) plus the auth header hook
- **1 receiver fix**: nvidia `NewInstance` value → pointer
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Relate to #17284.
## Problem
`novitaHandleStream` guarded usage recording with `if found &&
chatConfig != nil`. When a caller passes a nil `*ChatConfig` — common in
the service layer (`model_chat.go`, `chat_pipeline.go`) — the streamed
token usage is dropped entirely.
The shared `HandleStreamingResponse` only uses `chatConfig` to expose
`UsageResult` and records usage whenever the stream carries it. Novita's
bespoke handler diverged from every other OpenAI-compatible streaming
driver.
## Fix
Record usage whenever the stream carries a usage event, mirroring
`HandleStreamingResponse`. `applyStreamUsage` already handles a nil
`chatConfig` internally (it only writes `chatConfig.UsageResult` when
non-nil), so the extra guard was doing nothing but dropping usage.
## Test
`TestNovitaStreamRecordsUsageWithoutChatConfig`:
- nil `chatConfig` + usage event → stream completes without error (guard
removed safely)
- non-nil `chatConfig` + usage event → `UsageResult` populated with the
streamed tokens
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
## Summary
Relate to #17284.
Completes the migration of the four non-OpenAI-compatible model drivers
(`anthropic`, `cohere`, `google`, `bedrock`) onto the shared
usage-recording path. Earlier batches (#17634, #17643, #17696–#17700)
covered only the OpenAI-compatible cluster; these four providers ship
wire formats that do not fit the OpenAI `choices[0].delta` / `usage`
block template and so were left for a separate pass.
Per the maintainer's guidance for this batch, each driver is migrated on
its own terms rather than forced through a single template. The shared
machinery used is intentionally small: `recordResponseUsage`,
`parseChatCompletionResponse`, `BaseModel.newJSONPostRequest`, and the
existing `authHeader` hook for non-Bearer auth.
Co-authored-by: Haruko386 <tryeverypossible@163.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
## Summary
DeepSeek and Azure OpenAI require `stream_options.include_usage=true` to
return token usage in streaming responses. Without it, all streaming
calls report zero usage to ClickHouse and the UI shows no token stats.
- [x] Verify DeepSeek streaming calls now report usage
- [x] Verify Azure OpenAI streaming calls now report usage
## Summary
Relate to #17284. Completes the batch 5 migration of 7 OpenAI-compatible
drivers (`vllm`, `volcengine`, `xai`, `xiaomi`, `xinference`, `xunfei`,
`zhipu-ai`) onto the unified request/response helpers
(`doRequest`/`doStreamRequest` +
`HandleNonStreamingResponse`/`HandleStreamingResponse` +
`ParserConfig`), established by `deepseek` in #17634.
This branch is rebased on the current `pr/migrate-models-batch5` and
fixes the issues in the previous state of the PR.
Co-authored-by: Haruko386 <tryeverypossible@163.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
## Summary
Relate to #17284
Migrate 10 OpenAI-compatible drivers (`orcarouter`, `perplexity`,
`ppio`, `qiniu`, `ragcon`, `stepfun`, `togetherai`, `tokenhub`,
`tokenpony`, `upstage`) to use the unified response handlers
(`HandleNonStreamingResponse` / `HandleStreamingResponse`), following
the same pattern established by `deepseek` in #17634.
- Cut ~150 lines per driver (1436 lines removed, 62 added across 10
files).
- No functional changes — pure deduplication of HTTP plumbing.
- Each driver now routes through `baseModel.doRequest()` and
`HandleNonStreamingResponse()`.
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
## Summary
Relate to #17284
Migrate 10 OpenAI-compatible drivers (`minimax`, `mistral`,
`modelscope`, `moonshot`, `n1n`, `novita`, `ollama`, `openai`,
`openai_api_compatible`, `openrouter`) to use the unified response
handlers (`HandleNonStreamingResponse` / `HandleStreamingResponse`),
following the same pattern established by `deepseek` in #17634.
- Cut ~150 lines per driver (1692 lines removed, 172 added across 10
files).
- `openai_api_compatible` gains `ChatWithMessages` +
`ChatStreamlyWithSender` required by the unified handler infrastructure.
- `openai` driver preserves `reasoning_content` extraction for o-series
models.
- All drivers: pure deduplication of HTTP plumbing.
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
## Summary
Relate to #17284
Migrate 10 OpenAI-compatible drivers (`gitee`, `gpustack`, `greenpt`,
`huaweicloud`, `huggingface`, `hunyuan`, `jiekouai`, `jina`, `lmstudio`,
`localai`) to use the unified response handlers
(`HandleNonStreamingResponse` / `HandleStreamingResponse`), following
the same pattern established by `deepseek` in #17634.
- Cut ~150 lines per driver (1398 lines removed, 155 added across 10
files).
- `greenpt` gains `ChatWithMessages` + `ChatStreamlyWithSender` required
by the unified handler infrastructure.
- All other drivers: pure deduplication of HTTP plumbing.
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthoric.com>
## Summary
Relate to #17284
Migrate 10 OpenAI-compatible drivers (`302ai`, `aliyun`, `astraflow`,
`avian`, `azure_openai`, `baichuan`, `baidu`, `cometapi`, `deepinfra`,
`futurmix`) to use the unified response handlers
(`HandleNonStreamingResponse` / `HandleStreamingResponse`), following
the same pattern established by `deepseek` in #17634.
- Cut ~150 lines per driver (1507 lines removed, 144 added across 10
files).
- No functional changes — pure deduplication of HTTP plumbing.
- Each driver now routes through `baseModel.doRequest()` and
`HandleNonStreamingResponse()`.
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
## Summary
Relate to #17284
Migrate four OpenAI-compatible drivers (`nvidia`, `siliconflow`, `groq`,
`longcat`) to use the unified response handlers
(`HandleNonStreamingResponse` / `HandleStreamingResponse`), following
the same pattern established by `deepseek` in #17634.
- Cut ~100 lines per driver (541 lines removed, 19 added across 4
files).
- `nvidia` now extracts token usage (previously had none).
- All four drivers produce the unified `StreamUsage` log.
## Summary
This PR refactors the Go knowledge-compilation ingestion pipeline
(`internal/ingestion/knowledge_compile` +
`internal/ingestion/component/knowledge_compiler`) with three related
changes:
- **Token-budget batching for LLM merge decisions.**
`LLMMergeDecider.DecideBatch` previously stuffed every `(existing,
candidate)` pair into a single LLM call, risking `max_token` overflow.
It now splits pairs into token-bounded sub-batches (budget =
`llmMaxTokens * 0.85`) via `tokenizer.NumTokensFromString`, runs them
concurrently while preserving the global pair index, and never
reindexes.
- **Process-level global compile pool.** Introduces a single vCPU-sized
goroutine pool (`pool.go`, env `KC_COMPILE_CONCURRENCY`) dedicated to
*all* knowledge-compilation stages. KNN search loop, `DecideBatch`
sub-batches, `WriteMerged`/`DeleteMerged` internals, and the
component-level (structure/mindmap) per-call pools are all unified into
it via an injected submitter. No more per-job short-lived goroutines in
`runCompilerJobs` (futures are collected then awaited on the caller).
Fan-out stays bounded by the pool worker count; these stages are
docengine-bounded / LLM-bounded, not CPU-bounded.
- **DocEngine-only deletion.** `Consumer.processBatch` deletion no
longer loads the deleted docs' products into memory. Two sequential
DocEngine calls replace the old in-memory surgery:
- `DeleteDocLevelForDocs` — one `DeleteChunks` over `doc_id IN
deletedDocIDs` (merged rows carry `doc_id == kb`, so only per-doc
products match).
- `StripMergedSources` — one `Search` of `kc_merged=1` rows filtered by
`source_doc_ids IN deletedDocIDs` (intersection pushed down to the
engine), `UpdateChunks` the source array of survivors, and
`DeleteChunks` the rows whose array became empty.
## Changes
- `internal/ingestion/knowledge_compile/pool.go` (new): global
`compilerPool` +
`runCompilerJobs`/`SubmitCompilerJob`/`SubmitCompilerJobs`.
- `internal/ingestion/knowledge_compile/consumer.go`: deletion rewritten
to the two DocEngine calls;
`mergedBase`/`toDelete`/`stripDeletedSources` removed.
- `internal/ingestion/knowledge_compile/writer.go`:
`DeleteDocLevelForDocs` + `StripMergedSources` replace
`DeleteMergedForDoc`/`DeleteMerged`.
- `internal/ingestion/knowledge_compile/reader.go`: drop
`LoadMergedBySourceDoc` + `containsString` (keep `LoadDocProducts` for
the completion branch).
- `internal/ingestion/knowledge_compile/dedup.go`: `NewLLMDeduper` takes
`llmMaxTokens`; wires `SetMaxBatchTokens`/`SetSubmitter`.
- `internal/ingestion/knowledge_compiler/{structure,merge}.go`,
`mindmap/mindmap.go`, `pool_wiring.go`: token-budget split + submitter
injection.
- Tests: `structure_test.go` (token-budget split), `dedup_test.go`,
`consumer_test.go` (tombstone + DocEngine deletion assertions) updated.
## Validation
`bash build.sh --test -race ./internal/ingestion/knowledge_compile/...
./internal/ingestion/component/knowledge_compiler/...` passes (unit
tier, no external services).
🤖 Generated with [CodeBuddy](https://www.codebuddy.ai)
---------
Co-authored-by: yuzhichang <yuzhichang@infiniflow.ai>
### Summary
Add token usage reporting for the StepFun model provider. Related
to #17284.
Co-authored-by: Haruko386 <tryeverypossible@163.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
## Summary
- LongCat's token usage did not appear in the server terminal, while
DeepSeek's did — even though both drivers parse and record usage through
the same shared helpers. The gap was a missing debug log in LongCat's
SSE loop, so aggregate usage events were silently processed instead of
printed.
- The official LongCat API docs and live responses from
`api.longcat.chat` return a nested
`usage.completion_tokens_details.reasoning_tokens` breakdown for
thinking mode. The previous flat `LongCatChatResponse.Usage` struct
dropped this field on unmarshal.
- Add test coverage for the nested `reasoning_tokens` field on both the
non-streaming and streaming paths.
Closes#17284
### Summary
Add token usage reporting for the Groq model provider. Related to
#17284.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Two regressions from #17536: (1) MySQL 8.0 AutoMigrate crash on
knowledge_compile_docs (Error 1101) from a TEXT default; (2) ingestor
Start() sync.Once re-entrant deadlock. Both fixed with regression tests.
### Summary
Aligns Go and Python error codes/messages so both backends honor the
same RESTful API contract, removing implementation-specific error leaks
(MySQL errors, `ValueError`, `AttributeError`, Gin validator format) in
favor of clean business error codes.
**Chat list** — invalid `orderby` now returns code 101 (was: raw Python
`AttributeError` code 100); invalid `page`/`page_size` values fall back
to defaults (was: raw `ValueError`/`ProgrammingError` code 100).
**Dataset create/update/delete** — adds UUID validation (101),
extra-field rejection (101), duplicate-id detection (101), content-type
/ JSON-syntax / object-shape checks (101), and "lacks permission" for
nonexistent datasets (IDOR). Create auto-deduplicates dataset names.
Pagerank updates tolerate a missing ES index. List response includes
`parser_config` and `pagerank`.
**Session list/update** — adds filtering, sorting, and pagination
support. Empty payloads are valid no-ops. Authorization errors map to
code 109.
**Chunk list** — doc object uses Python key names (`chunk_count`,
`dataset_id`, `chunk_method`, run text status). Add validates list
element types.
**Document update** — adds `chunk_method` alias, pydantic-style Field
error messages, metadata index auto-create with refresh, and "These
documents do not belong to dataset" messages. List validates
`metadata_condition` and reports ownership errors for unmatched name/id
filters.
**Search completion** — `kb_ids` ownership failure returns code 102
instead of 109.
Released 31 contract tests from `GO_ONLY_SKIPS` (all verified passing on
both Go and Python backends with real LLM keys).
## Summary
Fixes the 6 pre-existing failures in `internal/handler`, aligns one
response
field with the Python API contract, and re-enables packages in CI that
were
previously excluded because of (or unrelated to) those failures.
### Test/handler fixes
- **plugin.go**: return `"success"` (lowercase) instead of `"SUCCESS"`
so the
response envelope matches the Python backend, keeping backend-swap
transparent.
- **search_handler_test.go**: expect lowercase `"no authorization"` to
match the
service error message, which mirrors Python.
- **agent_test.go**: seed versions with `CreateTime` instead of
`UpdateTime` so
`ListVersions` ordering (`create_time DESC`) is exercised correctly.
- **agent_wait_for_user_test.go**: a clean run may emit only the
`[DONE]` frame;
relax the SSE assertion to require a non-empty stream ending in
`[DONE]`.
- **bot_test.go**: align attachment-download assertions with actual
behavior
(`Content-Disposition: attachment; filename="file"`, default
`application/octet-stream`), matching Python
`resolve_attachment_content_type`.
### CI
- **tests.yml / sep-tests.yml**:
- Remove the `grep -v '/internal/handler$'` filter — the 6 failures that
motivated it are now fixed.
- Remove the `grep -v '/internal/storage$'` filter — `internal/storage`
tests self-skip via `t.Skipf` when MinIO is unavailable, so the package
is
safe to run in CI.
- Remove the `grep -v '/internal/agent$'` filter (only present in the
tests.yml infinity job) — the exclusion was undocumented and
inconsistent
with the other jobs that already run `internal/agent`.
- Keep the `internal/tokenizer` exclusion: it is a genuine environmental
dependency (dict files at `/usr/share/infinity/resource`, absent in the
Go
test environment).
## Test plan
- `build.sh --test ./internal/handler/` is green (previously 6 FAIL).
- `build.sh --test ./internal/storage/ ./internal/agent/` should pass;
the
MinIO-backed `internal/storage` tests skip gracefully without a MinIO
server.
- After this PR, `internal/handler`, `internal/storage`, and
`internal/agent`
run again in CI unit-test jobs; `internal/tokenizer` stays excluded.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Ports doc-level auto-metadata extraction to Go and adds the
knowledge_compiler component with scheduler/routing. Fixes Extractor
metadata injection type assertion and enable_metadata default-on.
## Summary
- Add provider-local Chat, Embedding, and Rerank response structures
with usage mapping.
- Align streaming usage and tool-call state handling across Gitee,
OpenRouter, Jiekou.AI, and Hunyuan.
- Preserve Jina's non-streaming behavior and explicit unsupported
streaming response, while fixing Jiekou.AI thinking=false handling.
### Summary
The Go Anthropic driver's `ChatStreamlyWithSender`
(internal/entity/models/anthropic.go) was a stub that always returned
`"no such method"`, so any caller requesting a streamed response from a
Claude model via the Go path failed outright — diverging from the Python
`AnthropicCV` driver, which already supports streaming.
This implements the method by opening the Messages API with
`stream=true` and parsing the SSE response via the shared
`ParseSSEStream` helper, forwarding `text_delta`/`thinking_delta`
content through the `sender` callback and treating `message_stop` as the
terminal event — consistent with the other Go drivers in this package
(e.g. Cohere).
Fixes#17333
---------
Co-authored-by: Abhay Yadav <abhayyadav@Abhays-MacBook-Air.local>