Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## Unreleased

- Logging: Local eval (`.eval`) and JSON (`.json`) log files are now written atomically (temp file + `fsync` + rename), preventing corruption from interrupted writes such as disk-full or process crash. (#2949)
- Anthropic: Support enabling model-generated citations for provided `ContentDocument` inputs.
- Checkpointing: In-sandbox restic artifacts moved from the world-listable `/opt/inspect-restic` to root-only `/root/.cache/inspect`, and egress scratch files no longer land in `/tmp`, so agents no longer see evidence of checkpointing.
- Eval: `EvalSample` and `EvalSampleSummary` now record `turn_count` and the sample's token limit (`token_limit`, `token_limit_type`, and metered `token_limit_usage`).
- Analysis: `samples_df` gains default `turn_count` and `token_limit_usage` columns, and `evals_df` configuration columns gain `token_limit_type`.
Expand Down
3 changes: 3 additions & 0 deletions src/inspect_ai/_util/content.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,9 @@ class ContentDocument(ContentBase):
mime_type: str = Field(default_factory=str)
"""Document mime type (automatically determined from 'document' if not specified)."""

citations: bool = Field(default=False)
"""Enable model-generated citations that reference spans of this document. Currently supported by Anthropic models; ignored by providers without document-citation support."""

@model_validator(mode="before")
@classmethod
def set_name_and_mime_type(cls, data: Any) -> Any:
Expand Down
10 changes: 7 additions & 3 deletions src/inspect_ai/model/_providers/anthropic.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
from anthropic.types import (
Base64PDFSourceParam,
CacheControlEphemeralParam,
CitationsConfigParam,
CodeExecutionToolResultBlock,
CodeExecutionToolResultBlockParam,
ContentBlock,
Expand Down Expand Up @@ -4068,9 +4069,12 @@ async def message_block_params(
source = PlainTextSourceParam(
type="text", media_type="text/plain", data=file_bytes.decode()
)
return [
DocumentBlockParam(type="document", source=source, title=content.filename)
]
document_block = DocumentBlockParam(
type="document", source=source, title=content.filename
)
if content.citations:
document_block["citations"] = CitationsConfigParam(enabled=True)
return [document_block]

elif isinstance(content, ContentData):
compaction_param = _compaction_from_content_data(content)
Expand Down
1 change: 1 addition & 0 deletions tests/dataset/test_content_document.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ def test_model_serialization():
"document": "/path/to/report.pdf",
"filename": "report.pdf",
"mime_type": "application/pdf",
"citations": False,
}


Expand Down
24 changes: 23 additions & 1 deletion tests/model/test_anthropic_convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@
Usage,
)

from inspect_ai._util.content import ContentReasoning, ContentText
from inspect_ai._util.content import ContentDocument, ContentReasoning, ContentText
from inspect_ai.model import (
model_output_from_anthropic,
)
from inspect_ai.model._chat_message import ChatMessageAssistant
from inspect_ai.model._model_output import ModelOutput
from inspect_ai.model._providers.anthropic import message_block_params


async def test_model_output_from_anthropic_basic() -> None:
Expand Down Expand Up @@ -52,6 +53,27 @@ async def test_model_output_from_anthropic_basic() -> None:
assert message_obj.content[0].text == "Hello! How can I help you today?"


async def test_message_block_params_enables_document_citations() -> None:
document = ContentDocument(
document="data:text/plain;base64,SGVsbG8=",
citations=True,
)

document_block = (await message_block_params(document))[0]

assert document_block["type"] == "document"
assert document_block.get("citations") == {"enabled": True}


async def test_message_block_params_omits_document_citations_by_default() -> None:
document = ContentDocument(document="data:text/plain;base64,SGVsbG8=")

document_block = (await message_block_params(document))[0]

assert document_block["type"] == "document"
assert "citations" not in document_block


async def test_model_output_from_anthropic_with_tool_use() -> None:
"""Test Message with tool use conversion."""
message = Message(
Expand Down