243 lines
7.8 KiB
Python
243 lines
7.8 KiB
Python
"""
|
|
End-to-end smoke test for document file upload + inference through
|
|
the ``openai-agents`` harness, driven by the mock LLM server.
|
|
|
|
Two file types are tested:
|
|
|
|
- ``test.md`` (text/markdown) — heading is "This is a test markdown
|
|
file"; the mock LLM returns a canned response quoting it back.
|
|
- ``test.pdf`` (application/pdf) — single-page PDF containing
|
|
"hello, world!"; the mock LLM returns a canned response
|
|
describing the content, proving the PDF document block reached
|
|
the model.
|
|
|
|
Each file type has its own test function. Run with::
|
|
|
|
.venv/bin/python -m pytest \\
|
|
tests/e2e/test_files_upload_e2e.py -v
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import uuid
|
|
from pathlib import Path
|
|
|
|
import httpx
|
|
|
|
from tests.e2e.conftest import (
|
|
configure_mock_llm,
|
|
create_runner_bound_session,
|
|
poll_session_until_terminal,
|
|
register_inline_agent,
|
|
reset_mock_llm,
|
|
send_user_message_to_session,
|
|
)
|
|
from tests.e2e.helpers import final_assistant_text
|
|
|
|
_REPO_ROOT = Path(__file__).resolve().parents[2]
|
|
|
|
# Checked-in test documents.
|
|
_TEST_MD_PATH = _REPO_ROOT / "tests" / "resources" / "test.md"
|
|
_TEST_PDF_PATH = _REPO_ROOT / "tests" / "resources" / "test.pdf"
|
|
|
|
|
|
def _bound_session_with_file(
|
|
client: httpx.Client,
|
|
*,
|
|
agent_name: str,
|
|
runner_id: str,
|
|
file_path: Path,
|
|
mime_type: str,
|
|
) -> tuple[str, str]:
|
|
"""
|
|
Create a runner-bound session, upload the file.
|
|
|
|
:param client: HTTP client pointed at the Omnigent server.
|
|
:param agent_name: Registered agent name.
|
|
:param runner_id: Live runner id to bind the session to.
|
|
:param file_path: Path to the file to upload.
|
|
:param mime_type: MIME type for the upload.
|
|
:returns: Tuple of ``(session_id, file_id)``.
|
|
"""
|
|
session_id = create_runner_bound_session(
|
|
client,
|
|
agent_name=agent_name,
|
|
runner_id=runner_id,
|
|
)
|
|
assert file_path.exists(), f"Test file missing at {file_path}. Restore from git."
|
|
file_bytes = file_path.read_bytes()
|
|
file_resp = client.post(
|
|
f"/v1/sessions/{session_id}/resources/files",
|
|
files={"file": (file_path.name, file_bytes, mime_type)},
|
|
)
|
|
file_resp.raise_for_status()
|
|
return session_id, file_resp.json()["id"]
|
|
|
|
|
|
def _send_and_poll(
|
|
client: httpx.Client,
|
|
*,
|
|
session_id: str,
|
|
file_id: str,
|
|
question: str,
|
|
) -> str:
|
|
"""
|
|
Post a user message (text + ``input_file``) to the session and
|
|
poll the snapshot until terminal, returning lowercased text.
|
|
|
|
:param client: HTTP client pointed at the Omnigent server.
|
|
:param session_id: Runner-bound session that owns the file.
|
|
:param file_id: The uploaded file ID.
|
|
:param question: The question to ask about the file.
|
|
:returns: Lowercased final assistant response text.
|
|
"""
|
|
response_id = send_user_message_to_session(
|
|
client,
|
|
session_id=session_id,
|
|
content=[
|
|
{"type": "input_text", "text": question},
|
|
{"type": "input_file", "file_id": file_id},
|
|
],
|
|
)
|
|
body = poll_session_until_terminal(
|
|
client,
|
|
session_id=session_id,
|
|
response_id=response_id,
|
|
timeout=120,
|
|
)
|
|
assert body["status"] == "completed", f"response failed: {body.get('error', 'unknown')}"
|
|
text = final_assistant_text(body).lower().strip()
|
|
assert text, "no assistant output text in response"
|
|
return text
|
|
|
|
|
|
def test_markdown_upload_reaches_llm(
|
|
http_client: httpx.Client,
|
|
live_runner_id: str,
|
|
mock_llm_server_url: str | None,
|
|
) -> None:
|
|
"""
|
|
Upload ``test.md`` and verify the LLM received its content.
|
|
|
|
Full AP-side e2e:
|
|
|
|
1. Register an inline agent with the openai-agents harness.
|
|
2. Configure the mock LLM to return a response quoting the heading.
|
|
3. Create a runner-bound session and upload ``test.md``
|
|
(text/markdown) via the session-scoped files API.
|
|
4. Post a user message (text + ``input_file``) asking the model
|
|
to quote the heading; poll the session snapshot until terminal.
|
|
5. Assert the response contains "test markdown file" — the exact
|
|
heading from the file — proving the markdown content reached
|
|
and was read by the model.
|
|
"""
|
|
model = f"mock-md-upload-{uuid.uuid4().hex[:6]}"
|
|
|
|
reset_mock_llm(mock_llm_server_url)
|
|
agent_name = register_inline_agent(
|
|
http_client,
|
|
name=f"files-md-e2e-{uuid.uuid4().hex[:6]}",
|
|
harness="openai-agents",
|
|
model=model,
|
|
profile="",
|
|
prompt=(
|
|
"You are a document analysis assistant. When the user "
|
|
"sends a file, read its content carefully and answer "
|
|
"questions about it accurately."
|
|
),
|
|
mock_llm_base_url=(f"{mock_llm_server_url}/v1" if mock_llm_server_url else None),
|
|
)
|
|
configure_mock_llm(
|
|
mock_llm_server_url,
|
|
[{"text": 'The heading says: "This is a test markdown file".'}],
|
|
key=model,
|
|
)
|
|
|
|
session_id, file_id = _bound_session_with_file(
|
|
http_client,
|
|
agent_name=agent_name,
|
|
runner_id=live_runner_id,
|
|
file_path=_TEST_MD_PATH,
|
|
mime_type="text/markdown",
|
|
)
|
|
|
|
text = _send_and_poll(
|
|
http_client,
|
|
session_id=session_id,
|
|
file_id=file_id,
|
|
question="What does the heading in this markdown file say? Quote it exactly.",
|
|
)
|
|
|
|
# test.md contains exactly: "# This is a test markdown file"
|
|
assert "test markdown file" in text, (
|
|
f"LLM did not quote the markdown heading — "
|
|
f"file content likely dropped before reaching the model. "
|
|
f"Full response:\n{text}"
|
|
)
|
|
|
|
|
|
def test_pdf_upload_reaches_llm(
|
|
http_client: httpx.Client,
|
|
live_runner_id: str,
|
|
mock_llm_server_url: str | None,
|
|
) -> None:
|
|
"""
|
|
Upload ``test.pdf`` and verify the LLM received the document.
|
|
|
|
Full AP-side e2e:
|
|
|
|
1. Register an inline agent with the openai-agents harness.
|
|
2. Configure the mock LLM to return a response describing the PDF.
|
|
3. Create a runner-bound session and upload ``test.pdf``
|
|
(application/pdf) via the session-scoped files API.
|
|
4. Post a user message (text + ``input_file``) asking whether the
|
|
document has content; poll the session snapshot until terminal.
|
|
5. Assert the response mentions PDF-related terms or the actual
|
|
content.
|
|
"""
|
|
model = f"mock-pdf-upload-{uuid.uuid4().hex[:6]}"
|
|
|
|
reset_mock_llm(mock_llm_server_url)
|
|
agent_name = register_inline_agent(
|
|
http_client,
|
|
name=f"files-pdf-e2e-{uuid.uuid4().hex[:6]}",
|
|
harness="openai-agents",
|
|
model=model,
|
|
profile="",
|
|
prompt=(
|
|
"You are a document analysis assistant. When the user "
|
|
"sends a file, read its content carefully and answer "
|
|
"questions about it accurately."
|
|
),
|
|
mock_llm_base_url=(f"{mock_llm_server_url}/v1" if mock_llm_server_url else None),
|
|
)
|
|
configure_mock_llm(
|
|
mock_llm_server_url,
|
|
[{"text": "This PDF document contains the text 'hello, world!' on a single page."}],
|
|
key=model,
|
|
)
|
|
|
|
session_id, file_id = _bound_session_with_file(
|
|
http_client,
|
|
agent_name=agent_name,
|
|
runner_id=live_runner_id,
|
|
file_path=_TEST_PDF_PATH,
|
|
mime_type="application/pdf",
|
|
)
|
|
|
|
text = _send_and_poll(
|
|
http_client,
|
|
session_id=session_id,
|
|
file_id=file_id,
|
|
question="Does this PDF document contain any text content? Describe what you see in it.",
|
|
)
|
|
|
|
# test.pdf is a single-page PDF containing "hello, world!".
|
|
_PDF_KEYWORDS = ("hello", "world", "pdf", "page", "document", "empty", "blank")
|
|
assert any(kw in text for kw in _PDF_KEYWORDS), (
|
|
f"LLM response doesn't mention the PDF contents — "
|
|
f"the PDF document block likely did not reach the model. "
|
|
f"Expected one of {_PDF_KEYWORDS!r} in response.\n"
|
|
f"Full response:\n{text}"
|
|
)
|