From 4d741aec7dc5f87517cb43a92fd79338143ff22b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 1 Dec 2025 03:54:06 +0000 Subject: [PATCH 1/8] Initial plan From 7033584046341aa593abbf9d65b185f88a941278 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 1 Dec 2025 04:01:20 +0000 Subject: [PATCH 2/8] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E4=B8=A5?= =?UTF-8?q?=E6=A0=BC=20Grounding=20=E6=A8=A1=E5=BC=8F=EF=BC=8C=E9=98=B2?= =?UTF-8?q?=E6=AD=A2=20AI=20=E5=9C=A8=E7=9F=A5=E8=AF=86=E5=BA=93=E4=BF=A1?= =?UTF-8?q?=E6=81=AF=E4=B8=8D=E8=B6=B3=E6=97=B6=E7=BC=96=E9=80=A0=E7=AD=94?= =?UTF-8?q?=E6=A1=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: BukeLy <19304666+BukeLy@users.noreply.github.com> --- docs/strict_grounding_mode.md | 148 ++++++++++++++++++++++ env.example | 14 +++ src/prompt_manager.py | 228 ++++++++++++++++++++++++++++++++-- src/tenant_config.py | 5 +- 4 files changed, 385 insertions(+), 10 deletions(-) create mode 100644 docs/strict_grounding_mode.md diff --git a/docs/strict_grounding_mode.md b/docs/strict_grounding_mode.md new file mode 100644 index 0000000..a5df739 --- /dev/null +++ b/docs/strict_grounding_mode.md @@ -0,0 +1,148 @@ +# 严格 Grounding 模式 + +## 问题背景 + +默认情况下,当知识库中的 chunks 不足以回答用户问题时,AI 可能会"强行编造"一个答案,即使这个答案没有依据。这是因为 LLM 有强大的生成能力,即使在没有足够上下文的情况下也会尝试给出"看起来合理"的回答。 + +## 解决方案 + +通过启用 **严格 Grounding 模式**,系统会使用增强版的 prompt,明确要求 AI 在信息不足时: + +1. **评估上下文充分性**:在生成答案前,先判断上下文是否足够回答问题 +2. **明确拒绝回答**:如果信息不足,使用标准化的拒绝回答格式 +3. **禁止编造内容**:严格禁止使用 AI 的通用知识来填补知识库的空白 + +## 使用方法 + +### 方式 1:环境变量(全局配置) + +在 `.env` 文件中添加: + +```bash +# 启用严格 Grounding 模式 +LIGHTRAG_STRICT_GROUNDING=true +``` + +### 方式 2:租户配置(租户级覆盖) + +通过 API 更新租户配置: + +```bash +curl -X PUT "http://localhost:8000/tenants/your_tenant/config" \ + -H "Content-Type: application/json" \ + -d '{ + "custom_prompts": { + "strict_grounding": "true" + } + }' +``` + +### 方式 3:完全自定义 Prompt + +如果需要更精细的控制,可以完全自定义 RAG 响应 prompt: + +```bash +# 环境变量方式 +LIGHTRAG_RAG_RESPONSE_PROMPT="你的自定义 prompt..." +LIGHTRAG_NAIVE_RAG_RESPONSE_PROMPT="你的自定义 naive 模式 prompt..." +``` + +或通过租户配置 API: + +```bash +curl -X PUT "http://localhost:8000/tenants/your_tenant/config" \ + -H "Content-Type: application/json" \ + -d '{ + "custom_prompts": { + "rag_response": "你的自定义 KG 模式 prompt...", + "naive_rag_response": "你的自定义 naive 模式 prompt..." + } + }' +``` + +## 配置优先级 + +从高到低: + +1. **租户配置的 `rag_response`/`naive_rag_response`**(完全自定义) +2. **环境变量 `LIGHTRAG_RAG_RESPONSE_PROMPT`/`LIGHTRAG_NAIVE_RAG_RESPONSE_PROMPT`** +3. **`strict_grounding=true`**(使用增强版默认 prompt) +4. **LightRAG 原生 prompt**(默认行为) + +## 增强版 Prompt 的关键指令 + +启用严格 Grounding 模式后,prompt 会包含以下关键指令: + +```markdown +---Critical Grounding Rules (MUST FOLLOW)--- + +⚠️ **ABSOLUTE REQUIREMENT**: You must ONLY use information explicitly stated in the **Context**. + +**Before generating any answer, you MUST evaluate:** +1. Does the Context contain information that DIRECTLY answers the user's question? +2. Is the information in the Context SUFFICIENT and RELEVANT to provide a complete answer? + +**If the answer is NO to either question, you MUST respond with:** +> 抱歉,根据当前知识库中的内容,我无法找到与您问题直接相关的信息。请尝试: +> - 重新表述您的问题 +> - 提供更多上下文信息 +> - 确认相关文档是否已上传到知识库 + +**DO NOT:** +- ❌ Make up or fabricate information not in the Context +- ❌ Use your general knowledge to fill gaps +- ❌ Provide speculative or assumed answers +- ❌ Say "based on my knowledge" or similar phrases +- ❌ Combine partial information to create misleading answers + +**DO:** +- ✅ Explicitly state when information is not available +- ✅ Only cite facts that appear in the Context +- ✅ Be honest about the limitations of the provided information +``` + +## 效果对比 + +### 未启用严格 Grounding 模式 + +用户问题:`公司的年度收入是多少?` + +(假设知识库中没有收入数据) + +AI 可能回答: +> 根据相关文档,该公司是一家成熟的企业...虽然具体年度收入数据未在文档中明确提及,但从其业务规模来看,估计年收入应该在... + +### 启用严格 Grounding 模式 + +同样的问题,AI 会回答: +> 抱歉,根据当前知识库中的内容,我无法找到与您问题直接相关的信息。请尝试: +> - 重新表述您的问题 +> - 提供更多上下文信息 +> - 确认相关文档是否已上传到知识库 + +## 刷新配置 + +修改配置后,需要刷新租户实例缓存: + +```bash +# 刷新特定租户 +curl -X POST "http://localhost:8000/tenants/your_tenant/config/refresh" + +# 或重启服务(全局生效) +docker compose restart rag-api +``` + +## 相关配置 + +| 配置项 | 类型 | 描述 | +|-------|------|------| +| `LIGHTRAG_STRICT_GROUNDING` | 环境变量 | 全局启用严格 Grounding 模式 | +| `strict_grounding` | 租户配置 | 租户级启用严格 Grounding 模式 | +| `rag_response` | 租户配置 | 完全自定义 KG 模式响应 prompt | +| `naive_rag_response` | 租户配置 | 完全自定义 naive 模式响应 prompt | + +## 注意事项 + +1. **语言适配**:当前默认拒绝回答消息是中文,如需英文或其他语言,请使用完全自定义 prompt +2. **性能影响**:严格 Grounding 模式不会影响性能,仅修改 prompt 内容 +3. **兼容性**:此功能与所有查询模式(naive、local、global、hybrid、mix)兼容 diff --git a/env.example b/env.example index adc5bf5..0ee970d 100644 --- a/env.example +++ b/env.example @@ -254,6 +254,20 @@ RAG_CONTEXT_MODE=page # 最大上下文 tokens RAG_MAX_CONTEXT_TOKENS=3000 +# ====== LightRAG 响应增强配置 ====== +# 控制 LLM 回答问题时的行为,防止在信息不足时编造答案 + +# --- 严格 Grounding 模式 --- +# 启用后,当知识库中没有足够信息回答问题时,AI 会明确拒绝回答 +# 而不是强行编造答案 +# 可选值: true, false(默认 false,不改变 LightRAG 原有行为) +LIGHTRAG_STRICT_GROUNDING=true + +# --- 自定义 RAG 响应 Prompt(可选)--- +# 完全自定义 RAG 响应 prompt,覆盖默认和增强版 +# LIGHTRAG_RAG_RESPONSE_PROMPT="你的自定义 prompt..." +# LIGHTRAG_NAIVE_RAG_RESPONSE_PROMPT="你的自定义 naive 模式 prompt..." + # ====== 存储后端配置 ====== # LightRAG 存储层配置(必须与 docker-compose 中的服务匹配) diff --git a/src/prompt_manager.py b/src/prompt_manager.py index c0b2d58..bacab90 100644 --- a/src/prompt_manager.py +++ b/src/prompt_manager.py @@ -4,22 +4,192 @@ Supports injecting custom prompts via: 1. Environment variables (global configuration) 2. Tenant configuration (tenant-specific override) + +Includes enhanced RAG response prompts that: +- Strictly refuse to answer when context is insufficient +- Require explicit "no information" responses +- Prevent AI from fabricating answers """ -import os import json -from typing import Dict, Any, Optional +import os +from typing import Any + from src.logger import logger +# Enhanced RAG response prompt with strict grounding requirements +ENHANCED_RAG_RESPONSE = """---Role--- + +You are an expert AI assistant specializing in synthesizing information from a provided knowledge base. Your primary function is to answer user queries accurately by ONLY using the information within the provided **Context**. + +---Goal--- + +Generate a comprehensive, well-structured answer to the user query. +The answer must integrate relevant facts from the Knowledge Graph and Document Chunks found in the **Context**. +Consider the conversation history if provided to maintain conversational flow and avoid repeating information. + +---Critical Grounding Rules (MUST FOLLOW)--- + +⚠️ **ABSOLUTE REQUIREMENT**: You must ONLY use information explicitly stated in the **Context**. + +**Before generating any answer, you MUST evaluate:** +1. Does the Context contain information that DIRECTLY answers the user's question? +2. Is the information in the Context SUFFICIENT and RELEVANT to provide a complete answer? + +**If the answer is NO to either question, you MUST respond with:** +> 抱歉,根据当前知识库中的内容,我无法找到与您问题直接相关的信息。请尝试: +> - 重新表述您的问题 +> - 提供更多上下文信息 +> - 确认相关文档是否已上传到知识库 + +**DO NOT:** +- ❌ Make up or fabricate information not in the Context +- ❌ Use your general knowledge to fill gaps +- ❌ Provide speculative or assumed answers +- ❌ Say "based on my knowledge" or similar phrases +- ❌ Combine partial information to create misleading answers + +**DO:** +- ✅ Explicitly state when information is not available +- ✅ Only cite facts that appear in the Context +- ✅ Be honest about the limitations of the provided information + +---Instructions--- + +1. Step-by-Step Instruction: + - Carefully determine the user's query intent in the context of the conversation history to fully understand the user's information need. + - Scrutinize both `Knowledge Graph Data` and `Document Chunks` in the **Context**. Identify and extract all pieces of information that are directly relevant to answering the user query. + - **CRITICAL**: If no relevant information is found, immediately respond with the "unable to answer" message above. Do NOT attempt to generate an answer. + - Weave the extracted facts into a coherent and logical response. Your own knowledge must ONLY be used to formulate fluent sentences and connect ideas, NOT to introduce any external information. + - Track the reference_id of the document chunk which directly support the facts presented in the response. Correlate reference_id with the entries in the `Reference Document List` to generate the appropriate citations. + - Generate a references section at the end of the response. Each reference document must directly support the facts presented in the response. + - Do not generate anything after the reference section. + +2. Content & Grounding: + - Strictly adhere to the provided context from the **Context**; DO NOT invent, assume, or infer any information not explicitly stated. + - If the answer cannot be found in the **Context**, state that you do not have enough information to answer. Do not attempt to guess. + +3. Formatting & Language: + - The response MUST be in the same language as the user query. + - The response MUST utilize Markdown formatting for enhanced clarity and structure (e.g., headings, bold text, bullet points). + - The response should be presented in {response_type}. + +4. References Section Format: + - The References section should be under heading: `### References` + - Reference list entries should adhere to the format: `* [n] Document Title`. Do not include a caret (`^`) after opening square bracket (`[`). + - The Document Title in the citation must retain its original language. + - Output each citation on an individual line + - Provide maximum of 5 most relevant citations. + - Do not generate footnotes section or any comment, summary, or explanation after the references. + +5. Reference Section Example: +``` +### References + +- [1] Document Title One +- [2] Document Title Two +- [3] Document Title Three +``` + +6. Additional Instructions: {user_prompt} + + +---Context--- + +{context_data} +""" + +# Enhanced Naive RAG response prompt with strict grounding requirements +ENHANCED_NAIVE_RAG_RESPONSE = """---Role--- + +You are an expert AI assistant specializing in synthesizing information from a provided knowledge base. Your primary function is to answer user queries accurately by ONLY using the information within the provided **Context**. + +---Goal--- + +Generate a comprehensive, well-structured answer to the user query. +The answer must integrate relevant facts from the Document Chunks found in the **Context**. +Consider the conversation history if provided to maintain conversational flow and avoid repeating information. + +---Critical Grounding Rules (MUST FOLLOW)--- + +⚠️ **ABSOLUTE REQUIREMENT**: You must ONLY use information explicitly stated in the **Context**. + +**Before generating any answer, you MUST evaluate:** +1. Does the Context contain information that DIRECTLY answers the user's question? +2. Is the information in the Context SUFFICIENT and RELEVANT to provide a complete answer? + +**If the answer is NO to either question, you MUST respond with:** +> 抱歉,根据当前知识库中的内容,我无法找到与您问题直接相关的信息。请尝试: +> - 重新表述您的问题 +> - 提供更多上下文信息 +> - 确认相关文档是否已上传到知识库 + +**DO NOT:** +- ❌ Make up or fabricate information not in the Context +- ❌ Use your general knowledge to fill gaps +- ❌ Provide speculative or assumed answers +- ❌ Say "based on my knowledge" or similar phrases +- ❌ Combine partial information to create misleading answers + +**DO:** +- ✅ Explicitly state when information is not available +- ✅ Only cite facts that appear in the Context +- ✅ Be honest about the limitations of the provided information + +---Instructions--- + +1. Step-by-Step Instruction: + - Carefully determine the user's query intent in the context of the conversation history to fully understand the user's information need. + - Scrutinize `Document Chunks` in the **Context**. Identify and extract all pieces of information that are directly relevant to answering the user query. + - **CRITICAL**: If no relevant information is found, immediately respond with the "unable to answer" message above. Do NOT attempt to generate an answer. + - Weave the extracted facts into a coherent and logical response. Your own knowledge must ONLY be used to formulate fluent sentences and connect ideas, NOT to introduce any external information. + - Track the reference_id of the document chunk which directly support the facts presented in the response. Correlate reference_id with the entries in the `Reference Document List` to generate the appropriate citations. + - Generate a **References** section at the end of the response. Each reference document must directly support the facts presented in the response. + - Do not generate anything after the reference section. + +2. Content & Grounding: + - Strictly adhere to the provided context from the **Context**; DO NOT invent, assume, or infer any information not explicitly stated. + - If the answer cannot be found in the **Context**, state that you do not have enough information to answer. Do not attempt to guess. + +3. Formatting & Language: + - The response MUST be in the same language as the user query. + - The response MUST utilize Markdown formatting for enhanced clarity and structure (e.g., headings, bold text, bullet points). + - The response should be presented in {response_type}. + +4. References Section Format: + - The References section should be under heading: `### References` + - Reference list entries should adhere to the format: `* [n] Document Title`. Do not include a caret (`^`) after opening square bracket (`[`). + - The Document Title in the citation must retain its original language. + - Output each citation on an individual line + - Provide maximum of 5 most relevant citations. + - Do not generate footnotes section or any comment, summary, or explanation after the references. + +5. Reference Section Example: +``` +### References + +- [1] Document Title One +- [2] Document Title Two +- [3] Document Title Three +``` + +6. Additional Instructions: {user_prompt} + + +---Context--- + +{content_data} +""" + def apply_custom_prompts( - tenant_id: Optional[str] = None, - tenant_custom_prompts: Optional[Dict[str, Any]] = None + tenant_id: str | None = None, + tenant_custom_prompts: dict[str, Any] | None = None ) -> None: """ Apply custom prompts to LightRAG global PROMPTS dictionary. - Priority: Tenant Config > Environment Variables > Default + Priority: Tenant Config > Environment Variables > Enhanced Defaults Args: tenant_id: Tenant ID (for logging) @@ -100,14 +270,54 @@ def apply_custom_prompts( except json.JSONDecodeError as e: logger.warning(f"Failed to parse entity_types JSON: {e}") + # 6. RAG Response Prompt (for knowledge graph queries) + rag_response = _get_prompt_value( + env_key="LIGHTRAG_RAG_RESPONSE_PROMPT", + tenant_key="rag_response", + tenant_config=tenant_custom_prompts + ) + if rag_response: + PROMPTS["rag_response"] = rag_response + applied_prompts.append("rag_response") + else: + # Apply enhanced default if not customized and strict_grounding is enabled + use_strict = _get_prompt_value( + env_key="LIGHTRAG_STRICT_GROUNDING", + tenant_key="strict_grounding", + tenant_config=tenant_custom_prompts + ) + if use_strict and use_strict.lower() in ("true", "1", "yes", "on"): + PROMPTS["rag_response"] = ENHANCED_RAG_RESPONSE + applied_prompts.append("rag_response(strict)") + + # 7. Naive RAG Response Prompt (for vector-only queries) + naive_rag_response = _get_prompt_value( + env_key="LIGHTRAG_NAIVE_RAG_RESPONSE_PROMPT", + tenant_key="naive_rag_response", + tenant_config=tenant_custom_prompts + ) + if naive_rag_response: + PROMPTS["naive_rag_response"] = naive_rag_response + applied_prompts.append("naive_rag_response") + else: + # Apply enhanced default if not customized and strict_grounding is enabled + use_strict = _get_prompt_value( + env_key="LIGHTRAG_STRICT_GROUNDING", + tenant_key="strict_grounding", + tenant_config=tenant_custom_prompts + ) + if use_strict and use_strict.lower() in ("true", "1", "yes", "on"): + PROMPTS["naive_rag_response"] = ENHANCED_NAIVE_RAG_RESPONSE + applied_prompts.append("naive_rag_response(strict)") + if applied_prompts: tenant_info = f"[Tenant {tenant_id}]" if tenant_id else "[Global]" logger.info(f"{tenant_info} Applied custom prompts: {', '.join(applied_prompts)}") def get_custom_entity_types( - tenant_custom_prompts: Optional[Dict[str, Any]] = None -) -> Optional[list]: + tenant_custom_prompts: dict[str, Any] | None = None +) -> list | None: """ Get custom entity types from environment or tenant configuration. @@ -141,8 +351,8 @@ def get_custom_entity_types( def _get_prompt_value( env_key: str, tenant_key: str, - tenant_config: Optional[Dict[str, Any]] -) -> Optional[str]: + tenant_config: dict[str, Any] | None +) -> str | None: """ Get prompt value with priority: Tenant Config > Environment Variable. diff --git a/src/tenant_config.py b/src/tenant_config.py index f027f27..23a3f2f 100644 --- a/src/tenant_config.py +++ b/src/tenant_config.py @@ -81,7 +81,10 @@ class TenantConfigModel(BaseModel): "entity_extraction_user_prompt": "你的自定义 user prompt...", "entity_continue_extraction_user_prompt": "你的自定义 continue prompt...", "entity_extraction_examples": ["示例1", "示例2"], - "entity_types": ["product", "feature", "error_code", "configuration"] + "entity_types": ["product", "feature", "error_code", "configuration"], + "strict_grounding": "true", + "rag_response": "你的自定义 RAG 响应 prompt(可选)...", + "naive_rag_response": "你的自定义 Naive RAG 响应 prompt(可选)..." } ) From a64b77adc9cb46e2660bf52e6f4edb33dde73269 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 1 Dec 2025 04:04:27 +0000 Subject: [PATCH 3/8] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E5=AE=A1=E6=9F=A5=E5=8F=91=E7=8E=B0=E7=9A=84=E9=97=AE=E9=A2=98?= =?UTF-8?q?=20-=20=E7=BB=9F=E4=B8=80=E5=BC=95=E7=94=A8=E6=A0=BC=E5=BC=8F?= =?UTF-8?q?=E5=92=8C=E6=8F=90=E5=8F=96=E8=BE=85=E5=8A=A9=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: BukeLy <19304666+BukeLy@users.noreply.github.com> --- src/prompt_manager.py | 53 +++++++++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/src/prompt_manager.py b/src/prompt_manager.py index bacab90..1268838 100644 --- a/src/prompt_manager.py +++ b/src/prompt_manager.py @@ -76,7 +76,7 @@ 4. References Section Format: - The References section should be under heading: `### References` - - Reference list entries should adhere to the format: `* [n] Document Title`. Do not include a caret (`^`) after opening square bracket (`[`). + - Reference list entries should adhere to the format: `- [n] Document Title`. Do not include a caret (`^`) after opening square bracket (`[`). - The Document Title in the citation must retain its original language. - Output each citation on an individual line - Provide maximum of 5 most relevant citations. @@ -158,7 +158,7 @@ 4. References Section Format: - The References section should be under heading: `### References` - - Reference list entries should adhere to the format: `* [n] Document Title`. Do not include a caret (`^`) after opening square bracket (`[`). + - Reference list entries should adhere to the format: `- [n] Document Title`. Do not include a caret (`^`) after opening square bracket (`[`). - The Document Title in the citation must retain its original language. - Output each citation on an individual line - Provide maximum of 5 most relevant citations. @@ -270,6 +270,9 @@ def apply_custom_prompts( except json.JSONDecodeError as e: logger.warning(f"Failed to parse entity_types JSON: {e}") + # Check if strict grounding is enabled (used by both rag_response and naive_rag_response) + use_strict_grounding = _is_strict_grounding_enabled(tenant_custom_prompts) + # 6. RAG Response Prompt (for knowledge graph queries) rag_response = _get_prompt_value( env_key="LIGHTRAG_RAG_RESPONSE_PROMPT", @@ -279,16 +282,9 @@ def apply_custom_prompts( if rag_response: PROMPTS["rag_response"] = rag_response applied_prompts.append("rag_response") - else: - # Apply enhanced default if not customized and strict_grounding is enabled - use_strict = _get_prompt_value( - env_key="LIGHTRAG_STRICT_GROUNDING", - tenant_key="strict_grounding", - tenant_config=tenant_custom_prompts - ) - if use_strict and use_strict.lower() in ("true", "1", "yes", "on"): - PROMPTS["rag_response"] = ENHANCED_RAG_RESPONSE - applied_prompts.append("rag_response(strict)") + elif use_strict_grounding: + PROMPTS["rag_response"] = ENHANCED_RAG_RESPONSE + applied_prompts.append("rag_response(strict)") # 7. Naive RAG Response Prompt (for vector-only queries) naive_rag_response = _get_prompt_value( @@ -299,16 +295,9 @@ def apply_custom_prompts( if naive_rag_response: PROMPTS["naive_rag_response"] = naive_rag_response applied_prompts.append("naive_rag_response") - else: - # Apply enhanced default if not customized and strict_grounding is enabled - use_strict = _get_prompt_value( - env_key="LIGHTRAG_STRICT_GROUNDING", - tenant_key="strict_grounding", - tenant_config=tenant_custom_prompts - ) - if use_strict and use_strict.lower() in ("true", "1", "yes", "on"): - PROMPTS["naive_rag_response"] = ENHANCED_NAIVE_RAG_RESPONSE - applied_prompts.append("naive_rag_response(strict)") + elif use_strict_grounding: + PROMPTS["naive_rag_response"] = ENHANCED_NAIVE_RAG_RESPONSE + applied_prompts.append("naive_rag_response(strict)") if applied_prompts: tenant_info = f"[Tenant {tenant_id}]" if tenant_id else "[Global]" @@ -348,6 +337,26 @@ def get_custom_entity_types( return None +def _is_strict_grounding_enabled( + tenant_config: dict[str, Any] | None +) -> bool: + """ + Check if strict grounding mode is enabled. + + Args: + tenant_config: Tenant custom prompts dictionary + + Returns: + bool: True if strict grounding is enabled + """ + use_strict = _get_prompt_value( + env_key="LIGHTRAG_STRICT_GROUNDING", + tenant_key="strict_grounding", + tenant_config=tenant_config + ) + return use_strict is not None and use_strict.lower() in ("true", "1", "yes", "on") + + def _get_prompt_value( env_key: str, tenant_key: str, From 4cc8df8259f7ddc73886c0037585513424a8fcd6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 1 Dec 2025 04:21:23 +0000 Subject: [PATCH 4/8] =?UTF-8?q?docs:=20=E6=B7=BB=E5=8A=A0=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2=E6=A8=A1=E5=BC=8F=E4=B8=8E=20Prompt=20=E5=AF=B9?= =?UTF-8?q?=E5=BA=94=E5=85=B3=E7=B3=BB=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: BukeLy <19304666+BukeLy@users.noreply.github.com> --- docs/strict_grounding_mode.md | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/docs/strict_grounding_mode.md b/docs/strict_grounding_mode.md index a5df739..cd88dd1 100644 --- a/docs/strict_grounding_mode.md +++ b/docs/strict_grounding_mode.md @@ -132,17 +132,32 @@ curl -X POST "http://localhost:8000/tenants/your_tenant/config/refresh" docker compose restart rag-api ``` +## Prompt 与查询模式的对应关系 + +LightRAG 有 5 种查询模式,但只使用 2 种响应 Prompt: + +| 查询模式 | 使用的 Prompt | 说明 | +|---------|--------------|------| +| `naive` | `naive_rag_response` | 纯向量搜索,不使用知识图谱 | +| `local` | `rag_response` | 局部知识图谱搜索 | +| `global` | `rag_response` | 全局知识图谱搜索 | +| `hybrid` | `rag_response` | 混合模式(local + global) | +| `mix` | `rag_response` | 全功能混合(KG + 向量) | + +因此,自定义 `rag_response` 会影响除 `naive` 以外的所有模式,而 `naive_rag_response` 仅影响 `naive` 模式。 + ## 相关配置 | 配置项 | 类型 | 描述 | |-------|------|------| | `LIGHTRAG_STRICT_GROUNDING` | 环境变量 | 全局启用严格 Grounding 模式 | | `strict_grounding` | 租户配置 | 租户级启用严格 Grounding 模式 | -| `rag_response` | 租户配置 | 完全自定义 KG 模式响应 prompt | -| `naive_rag_response` | 租户配置 | 完全自定义 naive 模式响应 prompt | +| `rag_response` | 租户配置 | 自定义 KG 模式响应 prompt(影响 local/global/hybrid/mix) | +| `naive_rag_response` | 租户配置 | 自定义 naive 模式响应 prompt(仅影响 naive) | ## 注意事项 1. **语言适配**:当前默认拒绝回答消息是中文,如需英文或其他语言,请使用完全自定义 prompt 2. **性能影响**:严格 Grounding 模式不会影响性能,仅修改 prompt 内容 3. **兼容性**:此功能与所有查询模式(naive、local、global、hybrid、mix)兼容 +4. **Prompt 复用**:LightRAG 的设计中,`rag_response` 被 local/global/hybrid/mix 四种模式共享 From fe23a33223d5dd6acd5fccaca777e211805d15f0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 1 Dec 2025 04:27:27 +0000 Subject: [PATCH 5/8] =?UTF-8?q?fix:=20=E5=A4=84=E7=90=86=20strict=5Fground?= =?UTF-8?q?ing=20=E9=85=8D=E7=BD=AE=E7=9A=84=E5=B8=83=E5=B0=94=E5=80=BC?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B=EF=BC=8C=E6=94=B9=E8=BF=9B=20env.example=20?= =?UTF-8?q?=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: BukeLy <19304666+BukeLy@users.noreply.github.com> --- env.example | 5 +++-- src/prompt_manager.py | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/env.example b/env.example index 0ee970d..db7a4f2 100644 --- a/env.example +++ b/env.example @@ -260,8 +260,9 @@ RAG_MAX_CONTEXT_TOKENS=3000 # --- 严格 Grounding 模式 --- # 启用后,当知识库中没有足够信息回答问题时,AI 会明确拒绝回答 # 而不是强行编造答案 -# 可选值: true, false(默认 false,不改变 LightRAG 原有行为) -LIGHTRAG_STRICT_GROUNDING=true +# 可选值: true, false +# 默认:注释掉或设置为 false(使用 LightRAG 原生行为) +# LIGHTRAG_STRICT_GROUNDING=true # 取消注释以启用严格 Grounding # --- 自定义 RAG 响应 Prompt(可选)--- # 完全自定义 RAG 响应 prompt,覆盖默认和增强版 diff --git a/src/prompt_manager.py b/src/prompt_manager.py index 1268838..7803aed 100644 --- a/src/prompt_manager.py +++ b/src/prompt_manager.py @@ -354,7 +354,8 @@ def _is_strict_grounding_enabled( tenant_key="strict_grounding", tenant_config=tenant_config ) - return use_strict is not None and use_strict.lower() in ("true", "1", "yes", "on") + # Handle both string and boolean values from tenant config + return use_strict is not None and str(use_strict).lower() in ("true", "1", "yes", "on") def _get_prompt_value( From 58bc7be6a688c9d040e351c48b690a30b377ca4e Mon Sep 17 00:00:00 2001 From: Bukely_ Date: Mon, 1 Dec 2025 12:35:45 +0800 Subject: [PATCH 6/8] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20prompt=5Fmanager.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/prompt_manager.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/prompt_manager.py b/src/prompt_manager.py index 7803aed..df30091 100644 --- a/src/prompt_manager.py +++ b/src/prompt_manager.py @@ -37,10 +37,7 @@ 2. Is the information in the Context SUFFICIENT and RELEVANT to provide a complete answer? **If the answer is NO to either question, you MUST respond with:** -> 抱歉,根据当前知识库中的内容,我无法找到与您问题直接相关的信息。请尝试: -> - 重新表述您的问题 -> - 提供更多上下文信息 -> - 确认相关文档是否已上传到知识库 +{unable_to_answer_message} **DO NOT:** - ❌ Make up or fabricate information not in the Context From e24f8dc9a05f6a502cb018092502889202150550 Mon Sep 17 00:00:00 2001 From: Bukely_ Date: Mon, 1 Dec 2025 12:42:42 +0800 Subject: [PATCH 7/8] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20prompt=5Fmanager.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/prompt_manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/prompt_manager.py b/src/prompt_manager.py index df30091..a38d030 100644 --- a/src/prompt_manager.py +++ b/src/prompt_manager.py @@ -140,7 +140,7 @@ - Scrutinize `Document Chunks` in the **Context**. Identify and extract all pieces of information that are directly relevant to answering the user query. - **CRITICAL**: If no relevant information is found, immediately respond with the "unable to answer" message above. Do NOT attempt to generate an answer. - Weave the extracted facts into a coherent and logical response. Your own knowledge must ONLY be used to formulate fluent sentences and connect ideas, NOT to introduce any external information. - - Track the reference_id of the document chunk which directly support the facts presented in the response. Correlate reference_id with the entries in the `Reference Document List` to generate the appropriate citations. + - Track the reference_id of the document chunks which directly support the facts presented in the response. Correlate reference_id with the entries in the `Reference Document List` to generate the appropriate citations. - Generate a **References** section at the end of the response. Each reference document must directly support the facts presented in the response. - Do not generate anything after the reference section. From 0fdf1af27dc7117ecf27e35c8558a76f2957c510 Mon Sep 17 00:00:00 2001 From: Bukely_ Date: Mon, 1 Dec 2025 12:42:48 +0800 Subject: [PATCH 8/8] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20prompt=5Fmanager.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/prompt_manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/prompt_manager.py b/src/prompt_manager.py index a38d030..34b918a 100644 --- a/src/prompt_manager.py +++ b/src/prompt_manager.py @@ -58,7 +58,7 @@ - Scrutinize both `Knowledge Graph Data` and `Document Chunks` in the **Context**. Identify and extract all pieces of information that are directly relevant to answering the user query. - **CRITICAL**: If no relevant information is found, immediately respond with the "unable to answer" message above. Do NOT attempt to generate an answer. - Weave the extracted facts into a coherent and logical response. Your own knowledge must ONLY be used to formulate fluent sentences and connect ideas, NOT to introduce any external information. - - Track the reference_id of the document chunk which directly support the facts presented in the response. Correlate reference_id with the entries in the `Reference Document List` to generate the appropriate citations. + - Track the reference_id of the document chunks which directly support the facts presented in the response. Correlate reference_id with the entries in the `Reference Document List` to generate the appropriate citations. - Generate a references section at the end of the response. Each reference document must directly support the facts presented in the response. - Do not generate anything after the reference section.