mirror of
https://github.com/tiennm99/DocsGPT.git
synced 2026-10-14 20:16:48 +00:00
Default retrieval to 6 chunks instead of 2
chunks is a total per request, split across the attached sources, so an agent with two sources and the default of 2 got a single chunk from each, and its answers changed with whichever chunk won. 6 gives three per source for about 4-5k more input tokens per retrieval turn. Every literal default moves from 2 to 6: the request default, the retrievers, the internal search tool, workflow agent nodes, scheduled and headless runs, agent create/update/import, the source retrieval config and the frontend forms. Existing agents and sources keep what they store; a source saved with chunks=2 now counts as configured at 2, which is pinned by a test. Headless runs also read chunks=0 as unset (`or 2`), so an agent with retrieval switched off retrieved anyway on scheduled runs; 0 now stays 0.
This commit is contained in:
1 parent
1c19ed8ce2
commit
ab3dbfa1be
33 files changed
+187
-46
No files matched your search
@@ -153,7 +153,9 @@ def _run_agent_headless(
|
||||
source_active = str(src_row["id"])
|
||||
retriever_kind = src_row.get("retriever", retriever_kind)
|
||||
source = {"active_docs": source_active}
|
||||
chunks = int(agent_config.get("chunks", 2) or 2)
|
||||
# ``chunks=0`` switches retrieval off; only a missing value takes the default.
|
||||
raw_chunks = agent_config.get("chunks")
|
||||
chunks = 6 if raw_chunks in (None, "") else int(raw_chunks)
|
||||
prompt_id = agent_config.get("prompt_id", "default")
|
||||
user_api_key = agent_config.get("key")
|
||||
agent_id = _resolve_agent_id(agent_config)
|
||||
|
||||
@@ -36,7 +36,7 @@ class InternalSearchTool(Tool):
|
||||
source=self.config.get("source", {}),
|
||||
chat_history=[],
|
||||
prompt="",
|
||||
chunks=int(self.config.get("chunks", 2)),
|
||||
chunks=int(self.config.get("chunks", 6)),
|
||||
doc_token_limit=int(self.config.get("doc_token_limit", 50000)),
|
||||
model_id=self.config.get("model_id", "docsgpt-local"),
|
||||
model_user_id=self.config.get("model_user_id"),
|
||||
@@ -464,7 +464,7 @@ def add_internal_search_tool(tools_dict: Dict, retriever_config: Dict) -> None:
|
||||
def build_internal_tool_config(
|
||||
source: Dict,
|
||||
retriever_name: str = "classic",
|
||||
chunks: int = 2,
|
||||
chunks: int = 6,
|
||||
doc_token_limit: int = 50000,
|
||||
sources: Optional[List[Dict]] = None,
|
||||
model_id: str = "docsgpt-local",
|
||||
|
||||
@@ -45,7 +45,7 @@ class AgentNodeConfig(BaseModel):
|
||||
stream_to_user: bool = True
|
||||
tools: List[str] = Field(default_factory=list)
|
||||
sources: List[str] = Field(default_factory=list)
|
||||
chunks: str = "2"
|
||||
chunks: str = "6"
|
||||
retriever: str = ""
|
||||
model_id: Optional[str] = None
|
||||
json_schema: Optional[Dict[str, Any]] = None
|
||||
|
||||
@@ -429,7 +429,7 @@ class WorkflowEngine:
|
||||
else {}
|
||||
),
|
||||
"retriever_name": node_config.retriever or "classic",
|
||||
"chunks": int(node_config.chunks) if node_config.chunks else 2,
|
||||
"chunks": int(node_config.chunks) if node_config.chunks else 6,
|
||||
"model_id": node_model_id,
|
||||
"llm_name": node_llm_name,
|
||||
"api_key": node_api_key,
|
||||
@@ -1388,7 +1388,7 @@ class WorkflowEngine:
|
||||
source={"active_docs": self._authorized_node_sources(node_config.sources)},
|
||||
chat_history=[],
|
||||
prompt="",
|
||||
chunks=int(node_config.chunks) if node_config.chunks else 2,
|
||||
chunks=int(node_config.chunks) if node_config.chunks else 6,
|
||||
decoded_token=self.agent.decoded_token,
|
||||
)
|
||||
docs = retriever.search(query)
|
||||
|
||||
@@ -46,7 +46,7 @@ class AnswerResource(Resource, BaseAnswerResource):
|
||||
required=False, default="default", description="Prompt ID"
|
||||
),
|
||||
"chunks": fields.Integer(
|
||||
required=False, default=2, description="Number of chunks"
|
||||
required=False, default=6, description="Number of chunks"
|
||||
),
|
||||
"retriever": fields.String(required=False, description="Retriever type"),
|
||||
"api_key": fields.String(required=False, description="API key"),
|
||||
|
||||
@@ -47,7 +47,7 @@ class StreamResource(Resource, BaseAnswerResource):
|
||||
required=False, default="default", description="Prompt ID"
|
||||
),
|
||||
"chunks": fields.Integer(
|
||||
required=False, default=2, description="Number of chunks"
|
||||
required=False, default=6, description="Number of chunks"
|
||||
),
|
||||
"retriever": fields.String(required=False, description="Retriever type"),
|
||||
"api_key": fields.String(required=False, description="API key"),
|
||||
|
||||
@@ -698,7 +698,7 @@ class StreamProcessor:
|
||||
"retriever": src_retriever or "classic",
|
||||
"chunks": (
|
||||
src_chunks if src_chunks is not None
|
||||
else data.get("chunks", "2")
|
||||
else data.get("chunks", "6")
|
||||
),
|
||||
# Per-source behaviour contract (lenient read).
|
||||
"retrieval": SourceConfig.parse(
|
||||
@@ -729,7 +729,7 @@ class StreamProcessor:
|
||||
"retriever": src_retriever or "classic",
|
||||
"chunks": (
|
||||
src_chunks if src_chunks is not None
|
||||
else data.get("chunks", "2")
|
||||
else data.get("chunks", "6")
|
||||
),
|
||||
"retrieval": SourceConfig.parse(
|
||||
source_doc.get("config")
|
||||
@@ -1056,7 +1056,7 @@ class StreamProcessor:
|
||||
)
|
||||
|
||||
retriever_name = "classic"
|
||||
chunks = 2
|
||||
chunks = 6
|
||||
|
||||
if self._agent_data is not None:
|
||||
# Agent-bound: agent wins, body's retriever/chunks are dropped.
|
||||
@@ -1068,7 +1068,7 @@ class StreamProcessor:
|
||||
except (ValueError, TypeError):
|
||||
logger.warning(
|
||||
f"Invalid agent chunks value: {self._agent_data['chunks']}, "
|
||||
"using default value 2"
|
||||
"using default value 6"
|
||||
)
|
||||
else:
|
||||
if "retriever" in self.data:
|
||||
@@ -1079,7 +1079,7 @@ class StreamProcessor:
|
||||
except (ValueError, TypeError):
|
||||
logger.warning(
|
||||
f"Invalid request chunks value: {self.data['chunks']}, "
|
||||
"using default value 2"
|
||||
"using default value 6"
|
||||
)
|
||||
# A source that configured its own retrieval knobs outranks the
|
||||
# request body: the owner tuned top-k for that corpus, a client
|
||||
@@ -1893,7 +1893,7 @@ class StreamProcessor:
|
||||
"retriever_name": self.retriever_config.get(
|
||||
"retriever_name", "classic"
|
||||
),
|
||||
"chunks": self.retriever_config.get("chunks", 2),
|
||||
"chunks": self.retriever_config.get("chunks", 6),
|
||||
"doc_token_limit": self.retriever_config.get(
|
||||
"doc_token_limit", 50000
|
||||
),
|
||||
|
||||
@@ -1552,9 +1552,9 @@ def apply_import(conn, user: str, doc: dict, resolution: Optional[dict] = None)
|
||||
slug = _unique_slug(agents_repo, user, metadata.get("slug") or spec.get("name"), exclude_id=exclude_id)
|
||||
|
||||
try:
|
||||
chunks_value = int(spec["chunks"]) if spec.get("chunks") is not None else 2
|
||||
chunks_value = int(spec["chunks"]) if spec.get("chunks") is not None else 6
|
||||
except (TypeError, ValueError):
|
||||
chunks_value = 2
|
||||
chunks_value = 6
|
||||
|
||||
# YAML-authoritative fields — written even when the resolved value is None,
|
||||
# so a re-import can CLEAR models / json_schema / prompt-to-default. On
|
||||
|
||||
@@ -259,7 +259,7 @@ def _format_agent_output(
|
||||
),
|
||||
"source": source_value,
|
||||
"sources": sources_list,
|
||||
"chunks": str(agent["chunks"]) if agent.get("chunks") is not None else "2",
|
||||
"chunks": str(agent["chunks"]) if agent.get("chunks") is not None else "6",
|
||||
"retriever": agent.get("retriever", "") or "",
|
||||
"prompt_id": str(agent["prompt_id"]) if agent.get("prompt_id") else "",
|
||||
"tools": agent.get("tools", []) or [],
|
||||
@@ -743,7 +743,7 @@ class CreateAgent(Resource):
|
||||
# For classic agents: default chunks/retriever if nothing else supplied.
|
||||
if agent_type != "workflow":
|
||||
if build_data.get("chunks") in (None, ""):
|
||||
build_data["chunks"] = 2
|
||||
build_data["chunks"] = 6
|
||||
if (
|
||||
not source_id_resolved
|
||||
and not extra_source_ids
|
||||
@@ -989,7 +989,7 @@ class UpdateAgent(Resource):
|
||||
elif field == "chunks":
|
||||
chunks_value = data.get("chunks")
|
||||
if chunks_value in ("", None):
|
||||
update_fields["chunks"] = 2
|
||||
update_fields["chunks"] = 6
|
||||
else:
|
||||
try:
|
||||
chunks_int = int(chunks_value)
|
||||
|
||||
@@ -74,7 +74,7 @@ def _ephemeral_agent_for_agentless(
|
||||
"user_id": user_id,
|
||||
"agent_type": "classic",
|
||||
"retriever": "classic",
|
||||
"chunks": 2,
|
||||
"chunks": 6,
|
||||
"prompt_id": "default",
|
||||
"source_id": None,
|
||||
"default_model_id": schedule.get("model_id") or "",
|
||||
|
||||
@@ -205,7 +205,7 @@ class ShareConversation(Resource):
|
||||
|
||||
if is_promptable:
|
||||
prompt_id_raw = data.get("prompt_id", "default")
|
||||
chunks_raw = data.get("chunks", "2")
|
||||
chunks_raw = data.get("chunks", "6")
|
||||
try:
|
||||
chunks_int = int(chunks_raw) if chunks_raw not in (None, "") else None
|
||||
except (TypeError, ValueError):
|
||||
|
||||
@@ -32,7 +32,7 @@ class ClassicRAG(BaseRetriever):
|
||||
source,
|
||||
chat_history=None,
|
||||
prompt="",
|
||||
chunks=2,
|
||||
chunks=6,
|
||||
doc_token_limit=50000,
|
||||
model_id="docsgpt-local",
|
||||
user_api_key=None,
|
||||
@@ -54,9 +54,9 @@ class ClassicRAG(BaseRetriever):
|
||||
self.chunks = int(chunks)
|
||||
except ValueError:
|
||||
logger.warning(
|
||||
f"Invalid chunks value '{chunks}', using default value 2"
|
||||
f"Invalid chunks value '{chunks}', using default value 6"
|
||||
)
|
||||
self.chunks = 2
|
||||
self.chunks = 6
|
||||
else:
|
||||
self.chunks = chunks
|
||||
user_id = decoded_token.get("sub") if decoded_token else "default"
|
||||
@@ -405,7 +405,7 @@ class ClassicRAG(BaseRetriever):
|
||||
|
||||
# ``chunks_per_source`` has a floor of 1 so no attached source is
|
||||
# starved, which means N sources always yield at least N documents —
|
||||
# ``chunks=2`` across 4 sources returned 4, though ``chunks`` is
|
||||
# ``chunks=6`` across 8 sources returned 8, though ``chunks`` is
|
||||
# documented as a top-k. Bound the overshoot to exactly that floor so
|
||||
# attaching more sources can no longer inflate the result without limit.
|
||||
# Ceiling on ``self.chunks`` (the actual fetch target), not
|
||||
|
||||
@@ -57,7 +57,7 @@ class Dispatcher(BaseRetriever):
|
||||
source,
|
||||
chat_history=None,
|
||||
prompt="",
|
||||
chunks=2,
|
||||
chunks=6,
|
||||
doc_token_limit=50000,
|
||||
model_id="docsgpt-local",
|
||||
user_api_key=None,
|
||||
|
||||
@@ -195,7 +195,7 @@ class GraphRAGRetriever(BaseRetriever):
|
||||
source,
|
||||
chat_history=None,
|
||||
prompt="",
|
||||
chunks=2,
|
||||
chunks=6,
|
||||
doc_token_limit=50000,
|
||||
model_id="docsgpt-local",
|
||||
user_api_key=None,
|
||||
|
||||
@@ -118,7 +118,7 @@ class RetrievalConfig(BaseModel):
|
||||
|
||||
retriever: str = "classic" # RetrieverCreator key
|
||||
exposure: str = "prefetch" # prefetch | agentic_tool (D11)
|
||||
chunks: int = 2 # final top-k
|
||||
chunks: int = 6 # final top-k
|
||||
score_threshold: Optional[float] = None # pgvector/mongo honor it; others ignore
|
||||
rephrase_query: bool = True # toggle ClassicRAG._rephrase_query side-call
|
||||
reranker: Optional[dict] = None # reserved: future cross-encoder/LLM reorder
|
||||
|
||||
Reference in new issue
Block a user