mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2026-09-03 05:10:16 +03:00
fix(engine): put the user request last in the planner prompt
This commit is contained in:
@@ -283,7 +283,7 @@ class PdfEditAgent:
|
|||||||
allow_need_content=can_request_content,
|
allow_need_content=can_request_content,
|
||||||
)
|
)
|
||||||
return await agent.select(
|
return await agent.select(
|
||||||
self._build_selection_prompt(request, supported_operations, unavailable_operations, repair_note)
|
self._build_selection_prompt(request, supported_operations, repair_note)
|
||||||
)
|
)
|
||||||
|
|
||||||
def _build_selection_agent(
|
def _build_selection_agent(
|
||||||
@@ -330,7 +330,6 @@ class PdfEditAgent:
|
|||||||
self,
|
self,
|
||||||
request: PdfEditRequest,
|
request: PdfEditRequest,
|
||||||
supported_operations: Iterable[ToolEndpoint],
|
supported_operations: Iterable[ToolEndpoint],
|
||||||
unavailable_operations: Iterable[ToolEndpoint],
|
|
||||||
repair_note: str = "",
|
repair_note: str = "",
|
||||||
) -> str:
|
) -> str:
|
||||||
repair_line = (
|
repair_line = (
|
||||||
@@ -343,35 +342,19 @@ class PdfEditAgent:
|
|||||||
if repair_note
|
if repair_note
|
||||||
else ""
|
else ""
|
||||||
)
|
)
|
||||||
unavailable_line = (
|
|
||||||
"Unavailable operations (exist but not currently usable): "
|
|
||||||
f"{self._get_operations_prompt(unavailable_operations)}\n"
|
|
||||||
if unavailable_operations
|
|
||||||
else ""
|
|
||||||
)
|
|
||||||
return (
|
return (
|
||||||
f"Conversation history:\n{format_conversation_history(request.conversation_history)}\n"
|
|
||||||
f"User request: {request.user_message}\n"
|
|
||||||
f"Files: {format_file_names(request.files)}\n"
|
|
||||||
f"Supported operations:\n{self._get_supported_operations_prompt(supported_operations)}\n"
|
f"Supported operations:\n{self._get_supported_operations_prompt(supported_operations)}\n"
|
||||||
f"{unavailable_line}"
|
|
||||||
f"{repair_line}"
|
f"{repair_line}"
|
||||||
f"Extracted page text:\n{format_page_text(request.page_text)}"
|
f"Conversation history:\n{format_conversation_history(request.conversation_history)}\n"
|
||||||
|
f"Files: {format_file_names(request.files)}\n"
|
||||||
|
f"Extracted page text:\n{format_page_text(request.page_text)}\n"
|
||||||
|
f"User request: {request.user_message}"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Endpoints that exist on the server and are callable via the direct API or the manual UI,
|
# Hidden from the AI planner only; still live for the manual UI, direct API and pipelines.
|
||||||
# but are never offered to the AI agent as a routing option.
|
# AUTO_REDACT and REDACT pre-date the unified operation model and take a less expressive
|
||||||
#
|
# schema, so AI redaction is channelled through REDACT_EXECUTE. Add an endpoint here when a
|
||||||
# Why: REDACT_EXECUTE is the preferred AI-driven redaction route. AUTO_REDACT and REDACT are
|
# legacy one has a preferred replacement the AI should use exclusively.
|
||||||
# legacy endpoints that remain fully functional for human callers (the manual redact UI, direct
|
|
||||||
# API consumers, pipelines) but would produce a worse experience if the AI routed to them —
|
|
||||||
# they accept a simpler, less expressive schema and pre-date the unified operation model.
|
|
||||||
# Hiding them here channels all AI redaction traffic through REDACT_EXECUTE without disabling
|
|
||||||
# the legacy endpoints for anyone else.
|
|
||||||
#
|
|
||||||
# How to reuse: add an endpoint here whenever a legacy endpoint has a preferred replacement
|
|
||||||
# that the AI should use exclusively. The endpoint remains live on the server; only the AI
|
|
||||||
# planner is prevented from selecting it.
|
|
||||||
_AGENT_HIDDEN_ENDPOINTS: frozenset[ToolEndpoint] = frozenset({ToolEndpoint.AUTO_REDACT, ToolEndpoint.REDACT})
|
_AGENT_HIDDEN_ENDPOINTS: frozenset[ToolEndpoint] = frozenset({ToolEndpoint.AUTO_REDACT, ToolEndpoint.REDACT})
|
||||||
|
|
||||||
def _classify_operations(self, request: PdfEditRequest) -> tuple[list[ToolEndpoint], list[ToolEndpoint]]:
|
def _classify_operations(self, request: PdfEditRequest) -> tuple[list[ToolEndpoint], list[ToolEndpoint]]:
|
||||||
|
|||||||
@@ -156,7 +156,6 @@ def test_repair_prompt_offers_reorder_or_telling_the_user(runtime: AppRuntime) -
|
|||||||
prompt = agent._build_selection_prompt(
|
prompt = agent._build_selection_prompt(
|
||||||
PdfEditRequest(user_message="anything", files=[]),
|
PdfEditRequest(user_message="anything", files=[]),
|
||||||
list(OPERATIONS),
|
list(OPERATIONS),
|
||||||
[],
|
|
||||||
"step 3 (SANITIZE_PDF) accepts PDF but the previous step produces IMAGE.",
|
"step 3 (SANITIZE_PDF) accepts PDF but the previous step produces IMAGE.",
|
||||||
)
|
)
|
||||||
assert "SANITIZE_PDF" in prompt
|
assert "SANITIZE_PDF" in prompt
|
||||||
@@ -494,11 +493,13 @@ def test_pdf_edit_selection_prompt_includes_unavailable_operations(runtime: AppR
|
|||||||
)
|
)
|
||||||
supported, unavailable = agent._classify_operations(request)
|
supported, unavailable = agent._classify_operations(request)
|
||||||
|
|
||||||
prompt = agent._build_selection_prompt(request, supported, unavailable)
|
selection_agent = agent._build_selection_agent(supported, unavailable, allow_need_content=False)
|
||||||
|
system_prompt = "".join(selection_agent.agent._system_prompts)
|
||||||
|
prompt = agent._build_selection_prompt(request, supported)
|
||||||
|
|
||||||
assert "Unavailable operations" in prompt
|
assert "NOT currently available" in system_prompt
|
||||||
assert "OCR_PDF" in prompt
|
assert "OCR_PDF" in system_prompt
|
||||||
assert ToolEndpoint.OCR_PDF.value in prompt
|
assert "OCR_PDF" not in prompt
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.anyio
|
@pytest.mark.anyio
|
||||||
|
|||||||
Reference in New Issue
Block a user