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:
arc53-machine committed 2026-09-28 14:34:50 +01:00
1 parent 1c19ed8ce2
commit ab3dbfa1be
33 files changed
+187 -46

No files matched your search

+1 -1
View File
@@ -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"),
+1 -1
View File
@@ -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
),
+2 -2
View File
@@ -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
+3 -3
View File
@@ -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)
+1 -1
View File
@@ -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 "",
+1 -1
View File
@@ -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):