fix: improve cross-device evidence, request diagnostics and prompt efficiency
This commit is contained in:
1 parent
621f30e437
commit
a66803651a
60 files changed
+3097
-160
No files matched your search
@@ -141,6 +141,74 @@ def _transcript_state(**overrides):
|
||||
return state
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("exploration", [False, True])
|
||||
@pytest.mark.parametrize("transcript", [False, True])
|
||||
async def test_plugin_result_is_delivered_with_pc_image_and_separate_phone_observation(
|
||||
tmp_path, exploration, transcript, monkeypatch
|
||||
):
|
||||
from langchain_openai import ChatOpenAI
|
||||
from PIL import Image
|
||||
|
||||
ctx = _transcript_ctx()
|
||||
ctx.exploration_id = "explore" if exploration else None
|
||||
monkeypatch.setattr(
|
||||
"artemis.exploration.runtime.exploration_messages",
|
||||
lambda _: [SystemMessage(content="Explore"), HumanMessage(content="Guidance")],
|
||||
)
|
||||
ctx.data_engine = MagicMock()
|
||||
ctx.data_engine.base_dir = str(tmp_path)
|
||||
pc = tmp_path / "pc.jpg"
|
||||
Image.new("RGB", (200, 100), "blue").save(pc)
|
||||
ctx.data_engine.get_image_path.return_value = pc
|
||||
node = OperatorNode(ctx, transcript_config=MemoryTranscriptConfig(enabled=transcript))
|
||||
ledger = node._ensure_transcript_ledger()
|
||||
tool = "plug_test_get_app_state"
|
||||
ledger.stage_turn(
|
||||
[
|
||||
AIMessage(content="", tool_calls=[{"name": tool, "args": {}, "id": "pc_call"}]),
|
||||
ToolMessage(content="Action Recorded", tool_call_id="pc_call"),
|
||||
]
|
||||
)
|
||||
report = {
|
||||
"status": "dispatched",
|
||||
"execution": [
|
||||
{
|
||||
"action": tool,
|
||||
"tool_call_id": "pc_call",
|
||||
"plugin_id": "test",
|
||||
"plugin_status": "success",
|
||||
"result": "PC Address bar",
|
||||
"post_image_name": "pc",
|
||||
}
|
||||
],
|
||||
}
|
||||
state = _transcript_state(structured_decisions="[]", last_execution_result=report)
|
||||
messages = await node._build_prompt(state, SCREENSHOT_B64, [], "PHONE_ELEMENTS", 2, [], "")
|
||||
if transcript:
|
||||
output = next(m for m in messages if isinstance(m, ToolMessage))
|
||||
assert output.tool_call_id == "pc_call" and "PC Address bar" in str(output.content)
|
||||
else:
|
||||
assert "PC Address bar" in str(messages)
|
||||
assert base64.b64encode(pc.read_bytes()).decode() in str(messages)
|
||||
assert SCREENSHOT_B64 not in str(messages) and "PHONE_ELEMENTS" in str(messages)
|
||||
wire = ChatOpenAI(model="fixture", api_key="fixture", use_responses_api=True, store=False)
|
||||
payload = wire._get_request_payload(messages)["input"]
|
||||
assert len([x for x in payload if x.get("type") == "function_call_output"]) == int(transcript)
|
||||
guided = await node._build_prompt(
|
||||
_transcript_state(
|
||||
structured_decisions="[]", last_execution_result=report, injected_instruction="回到手机"
|
||||
),
|
||||
SCREENSHOT_B64,
|
||||
[],
|
||||
"PHONE_ELEMENTS",
|
||||
3,
|
||||
[],
|
||||
"",
|
||||
)
|
||||
assert SCREENSHOT_B64 in str(guided)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize(
|
||||
"exploration,plugins", [(False, False), (True, False), (False, True), (True, True)]
|
||||
@@ -415,3 +483,38 @@ async def test_flag_off_keeps_legacy_two_message_build_and_no_ledger():
|
||||
assert isinstance(captured[0][0], SystemMessage)
|
||||
assert isinstance(captured[0][1], HumanMessage)
|
||||
assert ctx.transcript_ledger is None
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_exploration_guidance_appends_without_rewriting_static_prefix(monkeypatch):
|
||||
ctx = _transcript_ctx()
|
||||
ctx.exploration_id = "explore"
|
||||
guidance = ["initial guidance"]
|
||||
monkeypatch.setattr(
|
||||
"artemis.exploration.runtime.exploration_messages",
|
||||
lambda _: [SystemMessage(content="rules"), HumanMessage(content=guidance[0])],
|
||||
)
|
||||
node = OperatorNode(ctx, transcript_config=MemoryTranscriptConfig(enabled=True))
|
||||
state = _transcript_state()
|
||||
first = await node._build_prompt_transcript(state, "", "", 1, [], "")
|
||||
prefix = first[0].content
|
||||
assert "initial guidance" not in prefix
|
||||
assert "initial guidance" in str(first[-1].content)
|
||||
node._stage_transcript_turn(first)
|
||||
second = await node._build_prompt_transcript(state, "", "", 2, [], "")
|
||||
assert second[0].content == prefix
|
||||
assert "initial guidance" not in str(second[-1].content)
|
||||
node._stage_transcript_turn(second)
|
||||
guidance[0] = "new direction"
|
||||
third = await node._build_prompt_transcript(state, "", "", 3, [], "")
|
||||
assert third[0].content == prefix
|
||||
assert "new direction" in str(third[-1].content)
|
||||
# An interrupted/uncommitted build must not acknowledge away the guidance.
|
||||
retried = await node._build_prompt_transcript(state, "", "", 3, [], "")
|
||||
assert "new direction" in str(retried[-1].content)
|
||||
node._stage_transcript_turn(retried)
|
||||
await node._build_prompt_transcript(state, "", "", 4, [], "")
|
||||
ctx.transcript_ledger.freeze_turns(3, [HumanMessage(content="compressed history")])
|
||||
compacted = await node._build_prompt_transcript(state, "", "", 4, [], "")
|
||||
assert compacted[0].content == prefix
|
||||
assert "new direction" in str(compacted[-1].content)
|
||||
Reference in new issue
Block a user