## 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>
### Summary
Add token usage reporting for the LongCat (Meituan) model provider.
Related
to #17284.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
## Summary
GreenPT is a European AI provider with an OpenAI-compatible API,
optimized infrastructure, and datacenters powered by 100% renewable
energy.
This adds native GreenPT support across RAGFlow’s Go-first provider
system and its Python compatibility layer:
- discovers the current catalog from `GET /v1/models`
- features `glm-5.2` and `kimi-k2.7-code` for chat and coding
- supports `green-embedding` through `/v1/embeddings`
- supports `green-rerank` through `/v1/rerank`
- supports `green-s` and `green-s-pro` speech-to-text through
`/v1/listen`
- adds provider configuration, UI icon, and supported-provider
documentation
## Summary
- Parse chat, embedding, and rerank usage from provider responses
- Record usage with the correct model type even when no usage sink is
provided
- Cover SiliconFlow, Aliyun, Huawei Cloud, Qiniu, and VolcEngine
response formats
### Summary
The FunASR provider added in #17171 defaults to a local
`http://localhost:8000/v1` server, but it still inherited the global
API-key requirement and unconditionally built an Authorization header.
This prevented the default unauthenticated self-hosted deployment from
working. The transcription path also dereferenced a missing model name
while building its multipart request.
This change:
- allows an empty API key for FunASR, matching other local providers
- omits the Authorization header when no key is configured while
preserving trimmed Bearer authentication when one is provided
- validates and trims the ASR model name before building the multipart
request, returning an error instead of panicking
- adds HTTP-level regression coverage for unauthenticated
transcription/model listing and optional authentication
## Summary
Adds page-range parsing support to the Go-native pipeline path and
introduces strict `parse_type` validation for both dataset and document
update endpoints.
## What changed
### Pages range parsing
- **`internal/utility/pdf_pages.go`** — `NormalizePDFPages`: normalizes
raw page ranges (list of `[from,to]` 1-indexed inclusive ranges) into
sorted, merged, deduplicated `[][]int`. Invalid ranges are dropped.
- **`internal/ingestion/pipeline/pdf_pages.go`** —
`NormalizeParserConfigPages`: walks any parser_config map and normalizes
`"pages"` values under every component → filetype setup, so the
persisted config always carries clean, merged ranges.
- **`internal/deepdoc/parser/pdf/parser.go`** — integrates
`resolvePagesToProcess` to filter parsed PDF pages by the configured
ranges.
- Pipeline integration (parser pages):
`internal/parser/parser/pdf_parser_common.go`, `chunk_process.go`, plus
associated e2e and unit tests.
### Parse type validation (shared logic)
- **`internal/service/parser_mode.go`** (new) — `ValidateParseTypeMode`:
shared function that validates `parse_type` (1=BuiltIn/parser_id,
2=Pipeline/pipeline_id) and ensures the corresponding field is present.
Used by both dataset and document update endpoints.
- **`internal/service/dataset/crud.go`** / `update.go` — replaces inline
`isPipelineMode`/`isBuiltinMode` computation with the shared
`service.ValidateParseTypeMode`.
- **`internal/service/document/document_dataset_update.go`** — adds
strict `parse_type` validation in `validateDatasetDocumentUpdate`,
simplifies the reparse logic to a two-way switch (isBuiltin/isPipeline)
now that parse_type is always valid.
- **`internal/service/document/document.go`** — adds `ParseType` field
to `UpdateDatasetDocumentRequest`.
- **`internal/service/document/document_dataset_update.go`** —
`updateDocumentParserConfig` fallback path when DSL loading fails.
- **`internal/service/parser_mode_test.go`** (new) — test coverage for
nil, invalid, and missing-field scenarios.
### Frontend
- **`web/src/interfaces/request/document.ts`** — adds `parseType` to
`IChangeParserRequestBody`.
- **`web/src/hooks/use-document-request.ts`** —
`useSetDocumentPipelineParser` sends `parse_type` in the PATCH payload.
- **`web/src/pages/dataset/dataset/use-change-document-parser.ts`** —
Go/Python branching for the document parser config dialog.
-
**`web/src/components/document-pipeline-dialog/use-document-pipeline-form.ts`**
— `buildSubmitData` returns `parseType` (bugfix: was dropped from the
return value).
### Test changes
- **Removed**: 2 tests that verified the old "mutually exclusive" error
(replaced by `ValidateParseTypeMode` coverage).
- **Modified**: 6 tests across document and dataset packages to include
`ParseType` in request structs.
- **Added**: new e2e tests for pages parsing (`pages_e2e_test.go`,
`pdf_parser_pages_e2e_test.go`) and unit tests for `NormalizePDFPages`,
`NormalizeParserConfigPages`, `resolvePagesToProcess`.
## Backward compatibility
- The `parse_type` field is **required** when `parser_id` or
`pipeline_id` is sent. This changes the contract for both dataset and
document PATCH endpoints, but aligns the Go backend with the existing
frontend behavior (the frontend already sends `parse_type`). Callers
that omit `parse_type` when updating parser/pipeline selections will
receive a clear error message.
- Existing callers that only update fields like `name`, `enabled`, or
`meta_fields` are unaffected.
- Test updates ensure all known call sites are compliant.