Upgrade Ragflow to v0.25.2#19
Merged
Merged
Conversation
REST API langfuse api-key
Refactor: API file2document
### What problem does this PR solve? Before migration Web API: POST /v1/document/metadata/update After migration, Restful API PATCH /api/v2/datasets/<dataset_id>/documents/metadatas ### Type of change - [x] Refactoring
### What problem does this PR solve? migrate MCP APIs to RESTful api ### Type of change - [x] Refactoring
### What problem does this PR solve? As description. ### Type of change - [x] Refactoring
…#14318) Bumps [lxml](https://github.com/lxml/lxml) from 6.0.2 to 6.1.0. <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/lxml/lxml/blob/master/CHANGES.txt">lxml's changelog</a>.</em></p> <blockquote> <h1>6.1.0 (2026-04-17)</h1> <p>This release fixes a possible external entity injection (XXE) vulnerability in <code>iterparse()</code> and the <code>ETCompatXMLParser</code>.</p> <h2>Features added</h2> <ul> <li> <p>GH#486: The HTML ARIA accessibility attributes were added to the set of safe attributes in <code>lxml.html.defs</code>. This allows <code>lxml_html_clean</code> to pass them through. Patch by oomsveta.</p> </li> <li> <p>The default chunk size for reading from file-likes in <code>iterparse()</code> is now configurable with a new <code>chunk_size</code> argument.</p> </li> </ul> <h2>Bugs fixed</h2> <ul> <li>LP#2146291: The <code>resolve_entities</code> option was still set to <code>True</code> for <code>iterparse</code> and <code>ETCompatXMLParser</code>, allowing for external entity injection (XXE) when using these parsers without setting this option explicitly. The default was now changed to <code>'internal'</code> only (as for the normal XML and HTML parsers since lxml 5.0). Issue found by Sihao Qiu as CVE-2026-41066.</li> </ul> <h1>6.0.4 (2026-04-12)</h1> <h2>Bugs fixed</h2> <ul> <li>LP#2148019: Spurious MemoryError during namespace cleanup.</li> </ul> <h1>6.0.3 (2026-04-09)</h1> <h2>Bugs fixed</h2> <ul> <li> <p>Several out of memory error cases now raise <code>MemoryError</code> that were not handled before.</p> </li> <li> <p>Slicing with large step values (outside of <code>+/- sys.maxsize</code>) could trigger undefined C behaviour.</p> </li> <li> <p>LP#2125399: Some failing tests were fixed or disabled in PyPy.</p> </li> <li> <p>LP#2138421: Memory leak in error cases when setting the <code>public_id</code> or <code>system_url</code> of a document.</p> </li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/lxml/lxml/commit/43722f4402afa48b7890a96ce012eb0b9b1af5be"><code>43722f4</code></a> Update changelog.</li> <li><a href="https://github.com/lxml/lxml/commit/87470409b17188a5a7dbefcfa124af9cd792ffaa"><code>8747040</code></a> Name version of option change in docstring.</li> <li><a href="https://github.com/lxml/lxml/commit/6c36e6cef77db5087a1fff1a0d1ca8fed963afe7"><code>6c36e6c</code></a> Fix pypistats URL in download statistics script.</li> <li><a href="https://github.com/lxml/lxml/commit/c7d76d6cb817c8e1f316e43b16cab5e6ad669ad0"><code>c7d76d6</code></a> Change security policy to point to Github security advisories.</li> <li><a href="https://github.com/lxml/lxml/commit/378ccf82db8160928807c55ed580c0443aa94f42"><code>378ccf8</code></a> Update project income report.</li> <li><a href="https://github.com/lxml/lxml/commit/315270b810a9e3276c60daba549299d204ac962b"><code>315270b</code></a> Docs: Reduce TOC depth of package pages and move module contents first.</li> <li><a href="https://github.com/lxml/lxml/commit/6dbba7f3c72f655b05b26ef453fdee31af13ccf5"><code>6dbba7f</code></a> Docs: Show current year in copyright line.</li> <li><a href="https://github.com/lxml/lxml/commit/e4385bfa5d79527350d5ef17372fb70ba80b4cce"><code>e4385bf</code></a> Update project income report.</li> <li><a href="https://github.com/lxml/lxml/commit/5bed1e1a227cd9ba5a879aaeacdf504093a3f6e8"><code>5bed1e1</code></a> Validate file hashes in release download script.</li> <li><a href="https://github.com/lxml/lxml/commit/c13ee10a429f1144779bb1cbf6ae3bec808ae9c1"><code>c13ee10</code></a> Prepare release of 6.1.0.</li> <li>Additional commits viewable in <a href="https://github.com/lxml/lxml/compare/lxml-6.0.2...lxml-6.1.0">compare view</a></li> </ul> </details> <br /> [](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/infiniflow/ragflow/network/alerts). </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
### What problem does this PR solve? `check_ragflow_server_alive()` in `api/utils/health_utils.py` calls `requests.get(url)` without a `timeout` parameter. Unlike `check_minio_alive()` which correctly specifies `timeout=10`, this health check can hang indefinitely if the server is unresponsive. ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue) ### Changes Added `timeout=10` to the `requests.get()` call, consistent with `check_minio_alive()`. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
### What problem does this PR solve? Refact: system apis ### Type of change - [x] Refactoring
### What problem does this PR solve? migrate chunk APIs to RESTful routes ### Type of change - [x] Refactoring
### What problem does this PR solve? API refactor: stats_api and plugin_api ### Type of change - [x] Refactoring
…niflow#14328) ### What problem does this PR solve? Fix commit override from infiniflow#14298 of `api-key` to `api_key` ### Type of change - [x] Refactoring
### What problem does this PR solve? Feat: optimize title chunk 1. Add a new button to enable "Use root chunk as H0 heading", so that the first chunk is carried on to all remaining chunks. 2. Update resume agent template ### Type of change - [x] New Feature (non-breaking change which adds functionality) <img width="700" alt="img_v3_02111_63b04951-b3d7-4001-a08b-539db6d5298g" src="https://github.com/user-attachments/assets/4179ac4d-90e7-4353-9b93-d649a455e634" /> <img width="700" alt="image" src="https://github.com/user-attachments/assets/c0ba0f3c-05aa-4f2c-b418-e808ca1a2641" />
### What problem does this PR solve? remove legacy MCP server web API ### Type of change - [x] Refactoring
### What problem does this PR solve? when use azure blob as the file container, when click parse file, it calls: ```python partial(settings.STORAGE_IMPL.put, tenant_id=task["tenant_id"]) ``` So any storage backend used there must accept tenant_id as a kwarg. RAGFlowAzureSasBlob.put() did not, causing: ``` TypeError: ... got an unexpected keyword argument 'tenant_id' ``` Now it does, so parsing should proceed past this point. ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue)
### What problem does this PR solve?
1. **List agents**
**Prev API**:
- `/v1/canvas/list GET`
- `/api/v1/agents GET`
**Current API**: `/api/v2/agents GET`
2. **Get canvas template**
**Prev API**: `/v1/canvas/templates GET`
**Current API**: `/api/v2/agents/templates GET`
3. **Delete an agent**
**Prev API**:
- `/v1/canvas/rm POST`
- `/api/v1/agents/<agent_id> DELETE`
**Current API**: `/api/v2/agents/<agent_id> DELETE`
4. **Update an agent**
**Prev API**:
- `/api/v1/agents/<agent_id> PUT`
- `/v1/canvas/setting POST `
**Current API**: `/api/v2/agents/<agent_id> PATCH`
5. **Create an agent**
**Prev API**:
- `/v1/canvas/set POST`
- `/api/v1/agents POST`
**Current API**: `/api/v2/agents POST`
6. **Get an agent**
**Prev API**:
- `/v1/canvas/get/<canvas_id> GET `
**Current API**: `/api/v2/agents/<agent_id> GET`
7. **Reset an agent**
**Prev API**:
- `/v1/canvas/reset POST`
**Current API**: `/api/v2/agents/<agent_id>/reset POST`
8. **Upload a file to an agent**
**Prev API**:
- `/v1/canvas/upload/<canvas_id> POST`
**Current API**: `/api/v2/agents/<agent_id>/upload POST`
9. **Input form**
**Prev API**:
- `/v1/canvas/input_form GET`
**Current API**:
`/api/v2/agents/<agent_id>/components/<component_id>/input-form GET`
10. **Debug an agent**
**Prev API**:
- `/v1/canvas/debug POST`
**Current API**:
`/api/v2/agents/<agent_id>/components/<component_id>/debug POST`
11. **Trace an agent**
**Prev API**:
- `/v1/canvas/trace GET`
**Current API**: `/api/v2/agents/<agent_id>/logs/<message_id> GET`
12. **Get an agent version list**
**Prev API**:
- `/v1/canvas/getlistversion/<canvas_id>`
**Current API**: `/api/v2/agents/<agent_id>/versions GET`
13. **Get a version of agent**
**Prev API**:
- `/v1/canvas/getversion/<version_id>`
**Current API**: `/api/v2/agents/<agent_id>/versions/<version_id> GET`
14. **Test db connection**
**Prev API**:
- `/v1/canvas/test_db_connect POST`
**Current API**: `/api/v2/agents/test_db_connection`
15. **Rerun the agent**
**Prev API**:
- `/v1/canvas/rerun POST`
**Current API**: `/api/v2/agents/rerun POST`
16. **Get prompts**
**Prev API**:
- `/v1/canvas/prompts GET`
**Current API**: `/api/v2/agents/prompts GET`
### Type of change
- [x] New Feature (non-breaking change which adds functionality)
---------
Co-authored-by: chanx <1243304602@qq.com>
infiniflow#14205) The Langfuse Python SDK v3+ removed `start_generation()` method. RagFlow's code called this non-existent method, causing AttributeError when Langfuse tracing is enabled. Replace all `start_generation()` calls with `start_observation(as_type="generation")` which is the correct v4 SDK API. Affected files: - api/db/services/llm_service.py (12 occurrences) - api/db/services/dialog_service.py (1 occurrence) Fixes infiniflow#14204 Related to infiniflow#9243 ### What problem does this PR solve? _Briefly describe what this PR aims to solve. Include background context that will help reviewers understand the purpose of the PR._ ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue) --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
### What problem does this PR solve? Refactor user REST API ### Type of change - [x] Refactoring
### What problem does this PR solve? Feat: deepseek v4 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
### What problem does this PR solve? Implement retrieval_test in GO ### Type of change - [x] Refactoring
Fixes a small typo in the RAGFlow API key guide: `This documents provides` -> `This document provides`.
### What problem does this PR solve? Fix api user patch verb does not work ### Type of change - [ ] Bug Fix (non-breaking change which fixes an issue)
### What problem does this PR solve? migrate agent webhook routes to REST APIs ### Type of change - [x] Refactoring
### What problem does this PR solve? Allow image2text models (multimodal) to be used as chat models. ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue)
…flow#14218) Resolves infiniflow#14211 **Background:** Currently, RAGFlow routes all Docling parsing through the standard `/convert/source` endpoint. For large documents, this returns massive, unchunked text that exceeds RAGFlow's internal embedding model context limits, causing pipeline failures. **Solution:** This PR updates the `_parse_pdf_remote` ingestion logic in `docling_parser.py` to prioritize `docling-serve`'s native chunking endpoints (`/v1/chunk/source` and `/v1alpha/chunk/source`). - By receiving pre-sliced chunk objects directly from Docling, RAGFlow natively bypasses token limit overflows. - Included a graceful fallback mechanism to the standard `/convert/source` endpoints to maintain backwards compatibility for users running older versions of the Docling server that return 404s on the new routes. ### Type of change - [x] New Feature (non-breaking change which adds functionality)
…emove_last (infiniflow#14281) fix: check isinstance before len in VariableAssigner _remove_first/_remove_last
### What problem does this PR solve? Blob storage sync was downloading unsupported files first and rejecting them later, which wasted bandwidth and made sync slower. This PR skips unsupported extensions before download and applies `allow_images` in blob sync. fixes infiniflow#14338 ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue)
### What problem does this PR solve? Updated rootASHeadingTip. ### Type of change - [x] Documentation Update
…ctly. (infiniflow#14350) ### What problem does this PR solve? Fix: The button styles in the PaddleOCR dialog are not applying correctly. ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue) Co-authored-by: Copilot <copilot@github.com>
### What problem does this PR solve? Update API document ### Type of change - [ ] Documentation Update
### What problem does this PR solve? Updated a 0.25 faq. ### Type of change - [x] Documentation Update
### What problem does this PR solve? Fix: Route error in dataset files page ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue)
### What problem does this PR solve? Fix UI search multiple datasets ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue)
### What problem does this PR solve? The Aliyun Go driver has a stub `Rerank` method that always returns `"Aliyun, Rerank not implemented"`. DashScope exposes an OpenAI-compatible rerank endpoint (`compatible-mode/v1/rerank`) and hosts dedicated bilingual rerankers (`gte-rerank-v2`, `gte-rerank`) that are a natural pairing with the embedding models already in `aliyun.json`. Without this, Aliyun users cannot use reranking within RAGFlow. Closes infiniflow#14675 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
### What problem does this PR solve? As title ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue) Signed-off-by: Jin Hai <haijin.chn@gmail.com>
### What problem does this PR solve? ``` RAGFlow(admin)> list tasks; +-------------+------------------+----------------------------------+-------------+-----------+----------------------------------+----------+----------------------+-------------+-----------+---------+ | chunk_count | digest | document_id | duration | from_page | id | priority | progress | retry_count | task_type | to_page | +-------------+------------------+----------------------------------+-------------+-----------+----------------------------------+----------+----------------------+-------------+-----------+---------+ | 16 | 8a0016a0dc3cbdbb | f6aa38bb4ad111f1ba6338a74640adcc | 1511.156966 | 0 | f91e4f104ad111f1aaaf38a74640adcc | 0 | 1 | 1 | | 12 | +-------------+------------------+----------------------------------+-------------+-----------+----------------------------------+----------+----------------------+-------------+-----------+---------+ ``` ### Type of change - [x] New Feature (non-breaking change which adds functionality) --------- Signed-off-by: Jin Hai <haijin.chn@gmail.com>
### What problem does this PR solve? ### Type of change - [x] Documentation Update
…sions (infiniflow#14378) Fixes infiniflow#14360 ## Problem When the same blob storage bucket is connected to multiple knowledge bases (each through a different data source connector), the sync pipeline hashes only the blob path (`bucket_type:bucket_name:object_key`) to derive the document ID. Every connector pointing at the same bucket therefore produces **identical IDs** for the same object. The collision guard in `FileService.upload_document` then fires for the second knowledge base: ``` Existing document id collision with another knowledge base; skipping update. ``` This makes it impossible to index the same bucket into more than one KB simultaneously. ## Solution Include `connector_id` in the hash input so that each connector produces a distinct document ID even when the underlying blob path is identical: ```python # Before "id": hash128(doc.id), # After "id": hash128(f"{task['connector_id']}:{doc.id}"), ``` Because each KB connection uses its own connector (with a unique `connector_id`), documents are now namespaced per connector and no collision occurs. **Note:** This is a breaking change for existing synced data sources. After upgrading, a re-sync will create new documents with the updated ID format. Old documents (indexed under the previous format) will remain in the database but can be manually deleted or cleaned up via a re-sync with reindex enabled. ## Testing - Verified that the one-line change produces unique IDs for two connectors pointing at the same S3 path. - Existing unit test `test_upload_document_skips_cross_kb_document_id_collision` continues to pass — the collision guard in `FileService` is still valid for genuinely colliding IDs from other sources. --------- Co-authored-by: octo-patch <octo-patch@github.com>
…_model_service (infiniflow#14704) ## Summary - When a model is registered as `chat` in `tenant_llm` but has the `IMAGE2TEXT` tag in `llm_factories.json`, requesting it as `image2text` (e.g. PDF parser) fails with `Tenant Model with name <model> and type image2text not found`. - After resolution via the new fallback, the returned `config_dict["model_type"]` was still `"chat"`, causing `tenant_llm_service.model_instance()` to instantiate `ChatModel` instead of `CvModel` — breaking `describe_with_prompt` at ingestion time. ## What problem does this PR solve? RAGFlow already has a `CHAT→IMAGE2TEXT` fallback: when a chat model is not found, it retries with `image2text`. The symmetric fallback (`IMAGE2TEXT→CHAT`) was missing. This matters for multimodal models declared as `model_type: "chat"` with an `IMAGE2TEXT` tag in `llm_factories.json` (e.g. models added after tenant creation, or providers where a single model serves both purposes). The frontend PDF parser selector correctly surfaces these models via the `IMAGE2TEXT` tag, but the backend fails to resolve them at runtime. ## Type of change - [x] Bug Fix (non-breaking change which fixes an issue) ## Changes **`api/db/joint_services/tenant_model_service.py`** 1. Add `IMAGE2TEXT→CHAT` fallback in `get_model_config_by_type_and_name`: when an `image2text` model is not found in `tenant_llm`, retry with `chat` — but only if the `llm` table confirms `IMAGE2TEXT` capability via the `tags` field. This mirrors the philosophy of the existing `CHAT→IMAGE2TEXT` fallback: substitution is only allowed when the model has declared the required capability. 2. Normalize `config_dict["model_type"]` to `image2text` after the fallback, so the caller (`model_instance`) correctly routes to `CvModel` instead of `ChatModel`. 3. Extend the type validation guard to allow `(requested=image2text, found=chat)` alongside the existing `(requested=chat, found=image2text)` exception. ## Test plan - [ ] Add a model with `model_type=chat` and `tags` containing `IMAGE2TEXT` to a tenant - [ ] Select it as PDF parser in a knowledge base - [ ] Verify ingestion succeeds without `image2text not found` or `describe_with_prompt` errors - [ ] Verify the same model still works correctly in chat context 🤖 Generated with [Claude Code](https://claude.ai/claude-code) --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…finiflow#14087) ### What problem does this PR solve? The use_sql() function in dialog_service.py constructed SQL WHERE clauses and Infinity table names by directly interpolating kb_id values using Python f-strings, with no validation of the input values. A malformed or maliciously crafted kb_id (introduced via a compromised admin account or a separate injection vector) could alter the structure of the generated SQL query, potentially leading to unauthorized data access or data manipulation. This PR adds strict UUID format validation for all kb_id values before they are interpolated into any SQL string, causing requests with invalid IDs to fail fast with a ValueError rather than executing a tampered query. ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue) --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
…nfiniflow#14707) ## Summary - Adding a Bedrock model from the frontend fails with `Fail to access model(Bedrock/<model>).Expecting value: line 1 column 1 (char 0)`. - The assembled Bedrock JSON credentials are silently replaced by `"x"` before the connection test, causing `json.loads("x")` to raise a `JSONDecodeError`. ## What problem does this PR solve? Commit `050113482` introduced a fallback in `add_llm()` that reuses the existing DB key when `req.get("api_key") is None`: ```python if req.get("api_key") is None: api_key = existing_api_key if existing_api_key is not None else "x" ``` For Bedrock, credentials are sent as separate fields (`auth_mode`, `bedrock_ak`, `bedrock_sk`, `bedrock_region`, `aws_role_arn`) — the frontend does not send an `api_key` field. The function correctly assembles the JSON key: ```python api_key = apikey_json(["auth_mode", "bedrock_ak", "bedrock_sk", "bedrock_region", "aws_role_arn"]) ``` But since `req.get("api_key")` is `None`, the override immediately replaces `api_key` with `"x"` (or a stale DB value). `LiteLLMBase` then calls `json.loads("x")` for Bedrock auth → `JSONDecodeError`. ## Type of change - [x] Bug Fix (non-breaking change which fixes an issue) ## Changes **`api/apps/llm_app.py`** Write the assembled key into `req["api_key"]` so the `None` check evaluates to `False` and the override is skipped — consistent with how `Tencent Cloud` is already handled. ```python # Before api_key = apikey_json(["auth_mode", "bedrock_ak", "bedrock_sk", "bedrock_region", "aws_role_arn"]) # After req["api_key"] = apikey_json(["auth_mode", "bedrock_ak", "bedrock_sk", "bedrock_region", "aws_role_arn"]) api_key = req["api_key"] ``` ## Test plan - [ ] Configure a Bedrock provider in Model Providers with valid AWS credentials - [ ] Add a Bedrock chat model — verify no `Expecting value` error - [ ] Update the same model — verify the existing key is reused correctly when credentials fields are left empty 🤖 Generated with [Claude Code](https://claude.ai/claude-code) Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…rieval (infiniflow#13942) ## Summary - When KB retrieval fails (e.g. ES `AssertionError` on empty `index_names`), `kbinfos` falls back to a dict without a `total` key - `_async_update_chunk_info` then iterates over `chunk_info.keys()` (which includes `total`) and tries `kbinfos['total']`, raising a `KeyError` - This error surfaces when using Tavily web retrieval in a chat with no knowledge base attached ## Changes - Add `'total': 0` to all default `kbinfos` dicts in `_retrieve_information` - Add `setdefault('total', 0)` guard after successful KB retrieval to handle cases where the retrieval result omits the key - Accumulate `total` correctly in the merge branch of `_async_update_chunk_info` ## Test plan - [ ] Start a chat with Tavily configured and no knowledge base - [ ] Verify no `KeyError: 'total'` is raised - [ ] Verify Tavily results are returned correctly --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
### Type of change - [x] Documentation Update
### What problem does this PR solve? Bugfix: keep document api backward compatible Fix 1: infiniflow#14634 ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue)
… copy (infiniflow#14566) ### What 19 methods across `rag/llm/chat_model.py` and `rag/llm/cv_model.py` declare `gen_conf={}` (or `gen_conf: dict = {}`) as a parameter default and then mutate `gen_conf` in place — typically `del gen_conf["max_tokens"]`, `gen_conf["penalty_score"] = ...`, or `gen_conf.pop(...)` as part of provider-specific normalization. ### The two bugs in this pattern **1. Mutable default argument (Python footgun).** Python evaluates default values **once** at function-definition time, so the single `{}` dict is *shared* across every caller that doesn't pass `gen_conf`. The first such call's mutations leak into the default seen by every subsequent call. ```python # Before def chat_streamly(self, system, history, gen_conf={}, **kwargs): if "max_tokens" in gen_conf: del gen_conf["max_tokens"] # mutates the SHARED default dict ... ``` After call N with `max_tokens` set, call N+1 that omits `gen_conf` no longer sees `max_tokens` — even though the caller never touched it. **2. Caller-dict pollution.** When the caller *does* pass a `gen_conf` dict, the same in-place mutations modify the caller's dict. A reused `gen_conf` (very common for chat-loop callers that build the config once and pass it on every turn) silently loses `max_tokens`, `presence_penalty`, etc. after the first round. ### The fix In every affected method: - Change `gen_conf={}` (or `gen_conf: dict = {}`) → `gen_conf=None`. - Add `gen_conf = dict(gen_conf or {})` as the first statement of the body so all subsequent mutations operate on a fresh local copy. ```python # After def chat_streamly(self, system, history, gen_conf=None, **kwargs): gen_conf = dict(gen_conf or {}) if "max_tokens" in gen_conf: del gen_conf["max_tokens"] # local copy — safe ... ``` This is byte-for-byte identical provider-side behavior for callers that already pass a fresh `gen_conf` per call. The new `dict(...)` copy is O(small constant) per call. ### Files changed - `rag/llm/chat_model.py` — 17 methods - `rag/llm/cv_model.py` — 2 methods ### Tests Adds `test/unit_test/rag/llm/test_gen_conf_no_mutable_default.py` — an `ast`-based regression guard that walks both modules and asserts no parameter named `gen_conf` ever has a mutable literal (`{}` or `[]`) as its default. The test caught **five additional `gen_conf: dict = {}` sites** that an initial `gen_conf={}` text grep had missed (annotated parameters with whitespace), and would fail again if the pattern is ever reintroduced. ``` $ pytest test/unit_test/rag/llm/test_gen_conf_no_mutable_default.py -v ============================== 3 passed in 0.04s =============================== ``` `ruff check` passes on all touched files. ### Notes - This PR is intentionally focused on **just** the `gen_conf` default + copy fix. There's a related (but separate) `history.insert(0, ...)` pattern in the same files that mutates the caller's history list in 12 places — left for a follow-up so this PR stays mechanical and easy to review. ### Latest revision (`700bb54a7`) — addresses CodeRabbit review - Type annotation: `gen_conf: dict = None` → `gen_conf: dict | None = None` (5 occurrences in `chat_model.py`). The old annotation was a static-checker mismatch since `None` isn't a `dict`. - Regression test: the AST check accessed `default.keys` directly. `ast.List` has no `.keys` attribute — a future `gen_conf=[]` would crash with `AttributeError` instead of being caught. Use `getattr` for both `.keys` (Dict) and `.elts` (List). Manually verified the updated check correctly catches both `gen_conf={}` and `gen_conf=[]` while ignoring `gen_conf=None` and non-empty literals. --------- Co-authored-by: Ricardo <ricardo@example.com>
…ecks (infiniflow#14645) ### Related issues Closes infiniflow#14644 ### What problem does this PR solve? This PR fixes an authorization bug where datasets marked with `permission = me` could still be accessed by other members of the same tenant through APIs that relied on `KnowledgebaseService.accessible()` or `DocumentService.accessible()`. Before this change, those shared access helpers only checked tenant membership and did not enforce the dataset's permission mode. As a result, a non-owner who knew a private `dataset_id` could still reach downstream document and chunk operations even though the dataset was intended to be owner-only. This change updates the central access checks so that: - dataset owners always retain access - joined tenant members only get access when the dataset permission is `TEAM` - private datasets with `permission = me` remain inaccessible to non-owners - document-level access follows the same dataset permission rules The PR also adds regression coverage for private-vs-team dataset access behavior. ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue) - [ ] New Feature (non-breaking change which adds functionality) - [ ] Documentation Update - [ ] Refactoring - [ ] Performance Improvement - [ ] Other (please describe): ### Testing - Added `test/unit_test/api/db/services/test_dataset_access_permissions.py` - Attempted to run: `python -m pytest test\\unit_test\\api\\db\\services\\test_dataset_access_permissions.py -q` - Local execution in this workspace is currently blocked during test collection because the environment is missing the `strenum` dependency --------- Signed-off-by: Jin Hai <haijin.chn@gmail.com> Co-authored-by: jony376 <jony376@gmail.com> Co-authored-by: Wang Qi <wangq8@outlook.com> Co-authored-by: d 🔹 <liusway405@gmail.com> Co-authored-by: Jin Hai <haijin.chn@gmail.com> Co-authored-by: Magicbook1108 <newyorkupperbay@gmail.com> Co-authored-by: chanx <1243304602@qq.com> Co-authored-by: sxxtony <166789813+sxxtony@users.noreply.github.com> Co-authored-by: sxxtony <sxxtony@users.noreply.github.com> Co-authored-by: Baki Burak Öğün <63836730+bakiburakogun@users.noreply.github.com> Co-authored-by: bakiburakogun <bakiburakogun@users.noreply.github.com> Co-authored-by: Panda Dev <56657208+pandadev66@users.noreply.github.com> Co-authored-by: Haruko386 <tryeverypossible@163.com> Co-authored-by: D2758695161 <13510221939@163.com> Co-authored-by: Hunter <hunter@yitong.ai> Co-authored-by: Lynn <lynn_inf@hotmail.com> Co-authored-by: buua436 <sz_buua@foxmail.com> Co-authored-by: web-dev0521 <jasonpette1783@gmail.com> Co-authored-by: Tim Wang <38489718+wanghualoong@users.noreply.github.com> Co-authored-by: wanghualoong <wanghualoong@gmail.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: qinling0210 <88864212+qinling0210@users.noreply.github.com> Co-authored-by: dale053 <star05223@outlook.com>
### What problem does this PR solve? Implement `HuggingFace` provider ### Type of change - [x] New Feature (non-breaking change which adds functionality)
### What problem does this PR solve? tag parser id ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue)
### What problem does this PR solve? Fix: filter api in dataset document ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue)
### What problem does this PR solve? Added v0.25.2 release notes. ### Type of change - [x] Documentation Update
…w#14725) Close infiniflow#14292 ## Issue File ancestry endpoints return folder metadata without validating tenant permissions, allowing any authenticated user to query arbitrary `file_id` values across tenant boundaries. ## Affected Endpoints - `GET /v1/file/parent_folder?file_id={file_id}` - `GET /v1/file/all_parent_folder?file_id={file_id}` - `GET /api/v1/files/{id}/ancestors` ## Root Cause These endpoints **skip the permission check** that other file operations (Delete, Download, Move) perform. ## Expected Permission Check All file operations should follow this 3-step validation: - Check file.tenant_id - Check if user_id belongs to this tenant (via user_tenant join table) - Check KB permission type (team permission) **Code reference:** This is implemented in `checkFileTeamPermission()` and used by Delete/Download/Move, but **missing** from GetParentFolder/GetAllParentFolders. ## Reproduction ```bash # User B (tenant: BBB) accessing User A's file (tenant: AAA) curl -H "Authorization: Bearer USER_B_TOKEN" \ "http://localhost:9384/v1/file/parent_folder?file_id=AAA_FILE_123" # Result: Returns User A's folder metadata ❌ # Expected: "No authorization." ✅ Fix Pass userID from handler to service and call checkFileTeamPermission() — same as Download/Delete/Move handlers. --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
### What problem does this PR solve? Fix: Some bugs - Error during batch modification of metadata in the Knowledge Base - Manually configured metadata is not displayed in search settings ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue)
### What problem does this PR solve? Update mapping.json to treat id as a keyword. ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue)
### What problem does this PR solve? ``` RAGFlow(user)> embed text 'what is rag' 'who are you' with 'embedding-3@test@zhipu-ai' dimension 16; +-----------+-------+ | dimension | index | +-----------+-------+ | 16 | 0 | | 16 | 1 | +-----------+-------+ RAGFlow(user)> rerank query 'what is rag' document 'rag is retrieval augment generation' 'rag need llm' 'famous rag project includes ragflow' with 'rerank@test@zhipu-ai' top 2; +-------+-----------------+ | index | relevance_score | +-------+-----------------+ | 0 | 1 | | 2 | 0.99999976 | +-------+-----------------+ ``` ### Type of change - [x] New Feature (non-breaking change which adds functionality) Signed-off-by: Jin Hai <haijin.chn@gmail.com>
### What problem does this PR solve? Add legacy system healthz route ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue)
…nks (infiniflow#14732) ### What problem does this PR solve? ## Problem During the REST API refactoring (infiniflow#13690), the `/api/v2/kb/check_embedding` endpoint was removed and never migrated to the new RESTful structure. The frontend was pointed to the `/api/v1/datasets/{id}/embedding` endpoint (which is `run_embedding` — a completely different function). Additionally, a hard guard was introduced that rejects any `embd_id` change when `chunk_num > 0`, making it impossible to switch embedding models on datasets with existing chunks. ## Root Cause 1. **Missing endpoint**: The old `check_embedding` logic (sample random chunks, re-embed with the new model, compare cosine similarity) was not carried over to the new REST API service layer. 2. **Wrong frontend URL**: `checkEmbedding` in `api.ts` pointed to `/datasets/{id}/embedding` (`run_embedding`) instead of a dedicated check endpoint. 3. **Overly restrictive guard**: `dataset_api_service.py` line 310 blocked all `embd_id` updates when `chunk_num > 0`. This check did not exist in the pre-refactor code — it was incorrectly introduced during the refactor. ## Changes ### Backend - **`api/apps/services/dataset_api_service.py`** - Remove the `chunk_num > 0` hard guard on `embd_id` updates - Add `check_embedding()` service function: samples random chunks, re-embeds them with the candidate model, computes cosine similarity, returns compatibility result (avg ≥ 0.9 = compatible) - Add `import re` for the `_clean()` helper - **`api/apps/restful_apis/dataset_api.py`** - Add `POST /datasets/<dataset_id>/embedding/check` endpoint following the new REST API conventions - Clean up unused top-level imports (`random`, `re`, `numpy`) ### Frontend - **`web/src/utils/api.ts`** - Fix `checkEmbedding` URL from `/datasets/${datasetId}/embedding` → `/datasets/${datasetId}/embedding/check` ### Tests - **`test/testcases/test_http_api/test_dataset_management/test_update_dataset.py`** - Update `test_embedding_model_with_existing_chunks` to assert success (`code == 0`) instead of expecting the old `102` error - **`test/testcases/test_web_api/test_dataset_management/test_dataset_sdk_routes_unit.py`** - Update `test_update_route_branch_matrix_unit` to assert `RetCode.SUCCESS` when updating `embd_id` on a chunked dataset, replacing the old `chunk_num` error assertion ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue) --------- Signed-off-by: noob <yixiao121314@outlook.com>
### What problem does this PR solve? Updated v0.25.2 release date. ### Type of change - [x] Documentation Update
…iflow#14731) ### What problem does this PR solve? - Update version tags in README files (including translations) from v0.25.1 to v0.25.2 - Modify Docker image references and documentation to reflect new version - Update version badges and image descriptions - Maintain consistency across all language variants of README files ### Type of change - [x] Documentation Update
Alex-Welsh
approved these changes
May 11, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What problem does this PR solve?
Upgrade Ragflow to v0.25.2
Briefly describe what this PR aims to solve. Include background context that will help reviewers understand the purpose of the PR.
Type of change