pydantic-ai 0.0.48__tar.gz → 0.0.49__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pydantic-ai might be problematic. Click here for more details.
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/PKG-INFO +3 -3
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/evals/test_dataset.py +0 -4
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/evals/test_otel.py +40 -18
- pydantic_ai-0.0.49/tests/models/cassettes/test_anthropic/test_document_url_input.yaml +63 -0
- pydantic_ai-0.0.49/tests/models/cassettes/test_anthropic/test_image_url_input.yaml +62 -0
- pydantic_ai-0.0.49/tests/models/cassettes/test_openai_responses/test_openai_responses_model_builtin_tools.yaml +120 -0
- pydantic_ai-0.0.49/tests/models/cassettes/test_openai_responses/test_openai_responses_reasoning_generate_summary.yaml +105 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/test_anthropic.py +5 -7
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/test_openai_responses.py +61 -1
- pydantic_ai-0.0.49/tests/test_cli.py +191 -0
- pydantic_ai-0.0.48/tests/models/cassettes/test_anthropic/test_document_url_input.yaml +0 -340
- pydantic_ai-0.0.48/tests/models/cassettes/test_anthropic/test_image_url_input.yaml +0 -662
- pydantic_ai-0.0.48/tests/test_cli.py +0 -78
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/.gitignore +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/LICENSE +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/Makefile +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/README.md +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/pyproject.toml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/__init__.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/assets/dummy.pdf +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/assets/kiwi.png +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/assets/marcelo.mp3 +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/cassettes/test_mcp/test_agent_with_stdio_server.yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/conftest.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/evals/__init__.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/evals/test_evaluator_base.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/evals/test_evaluator_common.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/evals/test_evaluator_context.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/evals/test_evaluator_spec.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/evals/test_evaluators.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/evals/test_llm_as_a_judge.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/evals/test_render_numbers.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/evals/test_reporting.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/evals/test_reports.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/evals/test_utils.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/example_modules/README.md +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/example_modules/bank_database.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/example_modules/fake_database.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/example_modules/weather_service.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/graph/__init__.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/graph/test_file_persistence.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/graph/test_graph.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/graph/test_mermaid.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/graph/test_persistence.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/graph/test_state.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/graph/test_utils.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/import_examples.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/json_body_serializer.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/mcp_server.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/__init__.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_anthropic/test_document_binary_content_input.yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_anthropic/test_image_url_input_invalid_mime_type.yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_anthropic/test_multiple_parallel_tool_calls.yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_anthropic/test_text_document_url_input.yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_bedrock/test_bedrock_model.yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_bedrock/test_bedrock_model_anthropic_model_without_tools.yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_bedrock/test_bedrock_model_iter_stream.yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_bedrock/test_bedrock_model_max_tokens.yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_bedrock/test_bedrock_model_retry.yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_bedrock/test_bedrock_model_stream.yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_bedrock/test_bedrock_model_structured_response.yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_bedrock/test_bedrock_model_top_p.yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_bedrock/test_document_url_input.yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_bedrock/test_image_as_binary_content_input.yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_bedrock/test_image_url_input.yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_bedrock/test_text_as_binary_content_input.yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_bedrock/test_text_document_url_input.yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_cohere/test_request_simple_success_with_vcr.yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_gemini/test_document_url_input.yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_gemini/test_image_as_binary_content_input.yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_gemini/test_image_url_input.yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_groq/test_image_as_binary_content_input.yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_groq/test_image_url_input.yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_openai/test_audio_as_binary_content_input.yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_openai/test_document_url_input.yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_openai/test_image_as_binary_content_input.yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_openai/test_max_completion_tokens[gpt-4.5-preview].yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_openai/test_max_completion_tokens[gpt-4o-mini].yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_openai/test_max_completion_tokens[o3-mini].yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_openai/test_multiple_agent_tool_calls.yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_openai/test_openai_o1_mini_system_role[developer].yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_openai/test_openai_o1_mini_system_role[system].yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_openai/test_user_id.yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_openai_responses/test_audio_as_binary_content_input.yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_openai_responses/test_image_as_binary_content_input.yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_openai_responses/test_openai_responses_document_as_binary_content_input.yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_openai_responses/test_openai_responses_document_url_input.yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_openai_responses/test_openai_responses_image_url_input.yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_openai_responses/test_openai_responses_model_http_error.yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_openai_responses/test_openai_responses_model_retry.yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_openai_responses/test_openai_responses_model_simple_response.yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_openai_responses/test_openai_responses_model_simple_response_with_tool_call.yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_openai_responses/test_openai_responses_reasoning_effort.yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_openai_responses/test_openai_responses_result_type.yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_openai_responses/test_openai_responses_stream.yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_openai_responses/test_openai_responses_system_prompt.yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/cassettes/test_openai_responses/test_openai_responses_text_document_url_input.yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/mock_async_stream.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/test_bedrock.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/test_cohere.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/test_fallback.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/test_gemini.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/test_groq.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/test_instrumented.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/test_mistral.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/test_model.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/test_model_function.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/test_model_names.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/test_model_test.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/models/test_openai.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/providers/__init__.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/providers/cassettes/test_azure/test_azure_provider_call.yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/providers/cassettes/test_google_vertex/test_vertexai_provider.yaml +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/providers/test_anthropic.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/providers/test_azure.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/providers/test_bedrock.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/providers/test_cohere.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/providers/test_deepseek.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/providers/test_google_gla.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/providers/test_google_vertex.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/providers/test_groq.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/providers/test_mistral.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/providers/test_openai.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/providers/test_provider_names.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/test_agent.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/test_deps.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/test_examples.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/test_format_as_xml.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/test_json_body_serializer.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/test_live.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/test_logfire.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/test_mcp.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/test_messages.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/test_parts_manager.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/test_settings.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/test_streaming.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/test_tools.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/test_usage_limits.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/test_utils.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/typed_agent.py +0 -0
- {pydantic_ai-0.0.48 → pydantic_ai-0.0.49}/tests/typed_graph.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pydantic-ai
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.49
|
|
4
4
|
Summary: Agent Framework / shim to use Pydantic with LLMs
|
|
5
5
|
Project-URL: Homepage, https://ai.pydantic.dev
|
|
6
6
|
Project-URL: Source, https://github.com/pydantic/pydantic-ai
|
|
@@ -28,9 +28,9 @@ Classifier: Topic :: Internet
|
|
|
28
28
|
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
29
29
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
30
30
|
Requires-Python: >=3.9
|
|
31
|
-
Requires-Dist: pydantic-ai-slim[anthropic,bedrock,cli,cohere,evals,groq,mcp,mistral,openai,vertexai]==0.0.
|
|
31
|
+
Requires-Dist: pydantic-ai-slim[anthropic,bedrock,cli,cohere,evals,groq,mcp,mistral,openai,vertexai]==0.0.49
|
|
32
32
|
Provides-Extra: examples
|
|
33
|
-
Requires-Dist: pydantic-ai-examples==0.0.
|
|
33
|
+
Requires-Dist: pydantic-ai-examples==0.0.49; extra == 'examples'
|
|
34
34
|
Provides-Extra: logfire
|
|
35
35
|
Requires-Dist: logfire>=3.11.0; extra == 'logfire'
|
|
36
36
|
Description-Content-Type: text/markdown
|
|
@@ -164,16 +164,12 @@ async def test_add_evaluator(
|
|
|
164
164
|
'cases': [
|
|
165
165
|
{
|
|
166
166
|
'evaluators': [{'Python': 'ctx.output == 2'}],
|
|
167
|
-
'expected_output': None,
|
|
168
167
|
'inputs': {'query': 'What is 1+1?'},
|
|
169
|
-
'metadata': None,
|
|
170
168
|
'name': 'My Case 1',
|
|
171
169
|
},
|
|
172
170
|
{
|
|
173
171
|
'evaluators': [{'Python': 'ctx.output == 4'}],
|
|
174
|
-
'expected_output': None,
|
|
175
172
|
'inputs': {'query': 'What is 2+2?'},
|
|
176
|
-
'metadata': None,
|
|
177
173
|
'name': 'My Case 2',
|
|
178
174
|
},
|
|
179
175
|
],
|
|
@@ -245,26 +245,26 @@ async def test_span_tree_repr(span_tree: SpanTree):
|
|
|
245
245
|
""")
|
|
246
246
|
assert span_tree.repr_xml(include_span_id=True) == snapshot("""\
|
|
247
247
|
<SpanTree>
|
|
248
|
-
<SpanNode name='root' span_id=0000000000000001 >
|
|
249
|
-
<SpanNode name='child1' span_id=0000000000000003 >
|
|
250
|
-
<SpanNode name='grandchild1' span_id=0000000000000005 />
|
|
251
|
-
<SpanNode name='grandchild2' span_id=0000000000000007 />
|
|
248
|
+
<SpanNode name='root' span_id='0000000000000001' >
|
|
249
|
+
<SpanNode name='child1' span_id='0000000000000003' >
|
|
250
|
+
<SpanNode name='grandchild1' span_id='0000000000000005' />
|
|
251
|
+
<SpanNode name='grandchild2' span_id='0000000000000007' />
|
|
252
252
|
</SpanNode>
|
|
253
|
-
<SpanNode name='child2' span_id=0000000000000009 >
|
|
254
|
-
<SpanNode name='grandchild3' span_id=000000000000000b />
|
|
253
|
+
<SpanNode name='child2' span_id='0000000000000009' >
|
|
254
|
+
<SpanNode name='grandchild3' span_id='000000000000000b' />
|
|
255
255
|
</SpanNode>
|
|
256
256
|
</SpanNode>
|
|
257
257
|
</SpanTree>\
|
|
258
258
|
""")
|
|
259
259
|
assert span_tree.repr_xml(include_trace_id=True) == snapshot("""\
|
|
260
260
|
<SpanTree>
|
|
261
|
-
<SpanNode name='root' trace_id=00000000000000000000000000000001 >
|
|
262
|
-
<SpanNode name='child1' trace_id=00000000000000000000000000000001 >
|
|
263
|
-
<SpanNode name='grandchild1' trace_id=00000000000000000000000000000001 />
|
|
264
|
-
<SpanNode name='grandchild2' trace_id=00000000000000000000000000000001 />
|
|
261
|
+
<SpanNode name='root' trace_id='00000000000000000000000000000001' >
|
|
262
|
+
<SpanNode name='child1' trace_id='00000000000000000000000000000001' >
|
|
263
|
+
<SpanNode name='grandchild1' trace_id='00000000000000000000000000000001' />
|
|
264
|
+
<SpanNode name='grandchild2' trace_id='00000000000000000000000000000001' />
|
|
265
265
|
</SpanNode>
|
|
266
|
-
<SpanNode name='child2' trace_id=00000000000000000000000000000001 >
|
|
267
|
-
<SpanNode name='grandchild3' trace_id=00000000000000000000000000000001 />
|
|
266
|
+
<SpanNode name='child2' trace_id='00000000000000000000000000000001' >
|
|
267
|
+
<SpanNode name='grandchild3' trace_id='00000000000000000000000000000001' />
|
|
268
268
|
</SpanNode>
|
|
269
269
|
</SpanNode>
|
|
270
270
|
</SpanTree>\
|
|
@@ -302,9 +302,9 @@ async def test_span_node_repr(span_tree: SpanTree):
|
|
|
302
302
|
assert node is not None
|
|
303
303
|
|
|
304
304
|
leaf_node = span_tree.first({'name_equals': 'grandchild1'})
|
|
305
|
-
assert str(leaf_node) == snapshot("<SpanNode name='grandchild1' span_id=0000000000000005 />")
|
|
305
|
+
assert str(leaf_node) == snapshot("<SpanNode name='grandchild1' span_id='0000000000000005' />")
|
|
306
306
|
|
|
307
|
-
assert str(node) == snapshot("<SpanNode name='child2' span_id=0000000000000009>...</SpanNode>")
|
|
307
|
+
assert str(node) == snapshot("<SpanNode name='child2' span_id='0000000000000009'>...</SpanNode>")
|
|
308
308
|
assert repr(node) == snapshot("""\
|
|
309
309
|
<SpanNode name='child2' >
|
|
310
310
|
<SpanNode name='grandchild3' />
|
|
@@ -312,13 +312,13 @@ async def test_span_node_repr(span_tree: SpanTree):
|
|
|
312
312
|
""")
|
|
313
313
|
assert node.repr_xml(include_children=False) == snapshot("<SpanNode name='child2' children=... />")
|
|
314
314
|
assert node.repr_xml(include_span_id=True) == snapshot("""\
|
|
315
|
-
<SpanNode name='child2' span_id=0000000000000009 >
|
|
316
|
-
<SpanNode name='grandchild3' span_id=000000000000000b />
|
|
315
|
+
<SpanNode name='child2' span_id='0000000000000009' >
|
|
316
|
+
<SpanNode name='grandchild3' span_id='000000000000000b' />
|
|
317
317
|
</SpanNode>\
|
|
318
318
|
""")
|
|
319
319
|
assert node.repr_xml(include_trace_id=True) == snapshot("""\
|
|
320
|
-
<SpanNode name='child2' trace_id=00000000000000000000000000000001 >
|
|
321
|
-
<SpanNode name='grandchild3' trace_id=00000000000000000000000000000001 />
|
|
320
|
+
<SpanNode name='child2' trace_id='00000000000000000000000000000001' >
|
|
321
|
+
<SpanNode name='grandchild3' trace_id='00000000000000000000000000000001' />
|
|
322
322
|
</SpanNode>\
|
|
323
323
|
""")
|
|
324
324
|
assert node.repr_xml(include_start_timestamp=True) == snapshot("""\
|
|
@@ -383,6 +383,17 @@ async def test_span_tree_ancestors_methods():
|
|
|
383
383
|
assert not leaf_node.matches({'no_ancestor_has': {'name_matches_regex': 'root'}})
|
|
384
384
|
assert leaf_node.matches({'no_ancestor_has': {'name_matches_regex': 'abc'}})
|
|
385
385
|
|
|
386
|
+
# Test stop_recursing_when:
|
|
387
|
+
assert not leaf_node.matches(
|
|
388
|
+
{'some_ancestor_has': {'name_equals': 'level1'}, 'stop_recursing_when': {'name_equals': 'level2'}}
|
|
389
|
+
)
|
|
390
|
+
assert leaf_node.matches(
|
|
391
|
+
{'all_ancestors_have': {'name_matches_regex': 'level'}, 'stop_recursing_when': {'name_equals': 'level1'}}
|
|
392
|
+
)
|
|
393
|
+
assert leaf_node.matches(
|
|
394
|
+
{'no_ancestor_has': {'name_matches_regex': 'root'}, 'stop_recursing_when': {'name_equals': 'level1'}}
|
|
395
|
+
)
|
|
396
|
+
|
|
386
397
|
|
|
387
398
|
async def test_span_tree_descendants_methods():
|
|
388
399
|
"""Test the descendant traversal methods in SpanNode."""
|
|
@@ -462,6 +473,17 @@ async def test_span_tree_descendants_methods():
|
|
|
462
473
|
assert leaf_node.matches(negated_descendant_query)
|
|
463
474
|
assert leaf_node.matches({'no_descendant_has': {'has_attributes': {'depth': 4}}})
|
|
464
475
|
|
|
476
|
+
# Test stop_recursing_when:
|
|
477
|
+
assert not root_node.matches(
|
|
478
|
+
{'some_descendant_has': {'name_equals': 'leaf'}, 'stop_recursing_when': {'name_equals': 'level2'}}
|
|
479
|
+
)
|
|
480
|
+
assert root_node.matches(
|
|
481
|
+
{'all_descendants_have': {'has_attribute_keys': ['depth']}, 'stop_recursing_when': {'name_equals': 'level2'}}
|
|
482
|
+
)
|
|
483
|
+
assert root_node.matches(
|
|
484
|
+
{'no_descendant_has': {'name_equals': 'leaf'}, 'stop_recursing_when': {'name_equals': 'level3'}}
|
|
485
|
+
)
|
|
486
|
+
|
|
465
487
|
|
|
466
488
|
async def test_log_levels_and_exceptions():
|
|
467
489
|
"""Test recording different log levels and exceptions in spans."""
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
interactions:
|
|
2
|
+
- request:
|
|
3
|
+
headers:
|
|
4
|
+
accept:
|
|
5
|
+
- application/json
|
|
6
|
+
accept-encoding:
|
|
7
|
+
- gzip, deflate
|
|
8
|
+
connection:
|
|
9
|
+
- keep-alive
|
|
10
|
+
content-length:
|
|
11
|
+
- '267'
|
|
12
|
+
content-type:
|
|
13
|
+
- application/json
|
|
14
|
+
host:
|
|
15
|
+
- api.anthropic.com
|
|
16
|
+
method: POST
|
|
17
|
+
parsed_body:
|
|
18
|
+
max_tokens: 1024
|
|
19
|
+
messages:
|
|
20
|
+
- content:
|
|
21
|
+
- text: What is the main content on this document?
|
|
22
|
+
type: text
|
|
23
|
+
- source:
|
|
24
|
+
type: url
|
|
25
|
+
url: https://pdfobject.com/pdf/sample.pdf
|
|
26
|
+
type: document
|
|
27
|
+
role: user
|
|
28
|
+
model: claude-3-5-sonnet-latest
|
|
29
|
+
stream: false
|
|
30
|
+
uri: https://api.anthropic.com/v1/messages
|
|
31
|
+
response:
|
|
32
|
+
headers:
|
|
33
|
+
connection:
|
|
34
|
+
- keep-alive
|
|
35
|
+
content-length:
|
|
36
|
+
- '795'
|
|
37
|
+
content-type:
|
|
38
|
+
- application/json
|
|
39
|
+
transfer-encoding:
|
|
40
|
+
- chunked
|
|
41
|
+
parsed_body:
|
|
42
|
+
content:
|
|
43
|
+
- text: This document appears to be a sample PDF file that primarily contains Lorem ipsum text, which is placeholder
|
|
44
|
+
text commonly used in design and publishing. The document begins with "Sample PDF" and states "This is a simple
|
|
45
|
+
PDF file. Fun fun fun." followed by several paragraphs of Lorem ipsum text. The content doesn't convey any meaningful
|
|
46
|
+
information as Lorem ipsum is essentially dummy text used to demonstrate the visual form of a document without the
|
|
47
|
+
distraction of meaningful content.
|
|
48
|
+
type: text
|
|
49
|
+
id: msg_0146LphUoRKNWvDULHuTfu4H
|
|
50
|
+
model: claude-3-5-sonnet-20241022
|
|
51
|
+
role: assistant
|
|
52
|
+
stop_reason: end_turn
|
|
53
|
+
stop_sequence: null
|
|
54
|
+
type: message
|
|
55
|
+
usage:
|
|
56
|
+
cache_creation_input_tokens: 0
|
|
57
|
+
cache_read_input_tokens: 0
|
|
58
|
+
input_tokens: 2682
|
|
59
|
+
output_tokens: 96
|
|
60
|
+
status:
|
|
61
|
+
code: 200
|
|
62
|
+
message: OK
|
|
63
|
+
version: 1
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
interactions:
|
|
2
|
+
- request:
|
|
3
|
+
headers:
|
|
4
|
+
accept:
|
|
5
|
+
- application/json
|
|
6
|
+
accept-encoding:
|
|
7
|
+
- gzip, deflate
|
|
8
|
+
connection:
|
|
9
|
+
- keep-alive
|
|
10
|
+
content-length:
|
|
11
|
+
- '296'
|
|
12
|
+
content-type:
|
|
13
|
+
- application/json
|
|
14
|
+
host:
|
|
15
|
+
- api.anthropic.com
|
|
16
|
+
method: POST
|
|
17
|
+
parsed_body:
|
|
18
|
+
max_tokens: 1024
|
|
19
|
+
messages:
|
|
20
|
+
- content:
|
|
21
|
+
- text: What is this vegetable?
|
|
22
|
+
type: text
|
|
23
|
+
- source:
|
|
24
|
+
type: url
|
|
25
|
+
url: https://t3.ftcdn.net/jpg/00/85/79/92/360_F_85799278_0BBGV9OAdQDTLnKwAPBCcg1J7QtiieJY.jpg
|
|
26
|
+
type: image
|
|
27
|
+
role: user
|
|
28
|
+
model: claude-3-5-haiku-latest
|
|
29
|
+
stream: false
|
|
30
|
+
uri: https://api.anthropic.com/v1/messages
|
|
31
|
+
response:
|
|
32
|
+
headers:
|
|
33
|
+
connection:
|
|
34
|
+
- keep-alive
|
|
35
|
+
content-length:
|
|
36
|
+
- '660'
|
|
37
|
+
content-type:
|
|
38
|
+
- application/json
|
|
39
|
+
transfer-encoding:
|
|
40
|
+
- chunked
|
|
41
|
+
parsed_body:
|
|
42
|
+
content:
|
|
43
|
+
- text: This is a potato. It's a yellow-brown, oblong-shaped potato with a smooth skin and some small eyes or blemishes
|
|
44
|
+
visible on its surface. Potatoes are starchy root vegetables that are a staple food in many cuisines around the
|
|
45
|
+
world. They can be prepared in numerous ways, such as boiling, baking, frying, or mashing, and are rich in carbohydrates
|
|
46
|
+
and nutrients.
|
|
47
|
+
type: text
|
|
48
|
+
id: msg_01WCNHqrhEGCXhoC4G1ojDHN
|
|
49
|
+
model: claude-3-5-haiku-20241022
|
|
50
|
+
role: assistant
|
|
51
|
+
stop_reason: end_turn
|
|
52
|
+
stop_sequence: null
|
|
53
|
+
type: message
|
|
54
|
+
usage:
|
|
55
|
+
cache_creation_input_tokens: 0
|
|
56
|
+
cache_read_input_tokens: 0
|
|
57
|
+
input_tokens: 296
|
|
58
|
+
output_tokens: 93
|
|
59
|
+
status:
|
|
60
|
+
code: 200
|
|
61
|
+
message: OK
|
|
62
|
+
version: 1
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
interactions:
|
|
2
|
+
- request:
|
|
3
|
+
headers:
|
|
4
|
+
accept:
|
|
5
|
+
- application/json
|
|
6
|
+
accept-encoding:
|
|
7
|
+
- gzip, deflate
|
|
8
|
+
connection:
|
|
9
|
+
- keep-alive
|
|
10
|
+
content-length:
|
|
11
|
+
- '217'
|
|
12
|
+
content-type:
|
|
13
|
+
- application/json
|
|
14
|
+
host:
|
|
15
|
+
- api.openai.com
|
|
16
|
+
method: POST
|
|
17
|
+
parsed_body:
|
|
18
|
+
input:
|
|
19
|
+
- content: Give me the best news about LLMs from the last 24 hours. Be short.
|
|
20
|
+
role: user
|
|
21
|
+
instructions: ''
|
|
22
|
+
model: gpt-4o
|
|
23
|
+
stream: false
|
|
24
|
+
tool_choice: auto
|
|
25
|
+
tools:
|
|
26
|
+
- type: web_search_preview
|
|
27
|
+
uri: https://api.openai.com/v1/responses
|
|
28
|
+
response:
|
|
29
|
+
headers:
|
|
30
|
+
alt-svc:
|
|
31
|
+
- h3=":443"; ma=86400
|
|
32
|
+
connection:
|
|
33
|
+
- keep-alive
|
|
34
|
+
content-length:
|
|
35
|
+
- '3210'
|
|
36
|
+
content-type:
|
|
37
|
+
- application/json
|
|
38
|
+
openai-organization:
|
|
39
|
+
- pydantic-28gund
|
|
40
|
+
openai-processing-ms:
|
|
41
|
+
- '2843'
|
|
42
|
+
openai-version:
|
|
43
|
+
- '2020-10-01'
|
|
44
|
+
strict-transport-security:
|
|
45
|
+
- max-age=31536000; includeSubDomains; preload
|
|
46
|
+
transfer-encoding:
|
|
47
|
+
- chunked
|
|
48
|
+
parsed_body:
|
|
49
|
+
created_at: 1743506361
|
|
50
|
+
error: null
|
|
51
|
+
id: resp_67ebcbb93728819197f923ff16e98bce04f5055a2a33abc3
|
|
52
|
+
incomplete_details: null
|
|
53
|
+
instructions: ''
|
|
54
|
+
max_output_tokens: null
|
|
55
|
+
metadata: {}
|
|
56
|
+
model: gpt-4o-2024-08-06
|
|
57
|
+
object: response
|
|
58
|
+
output:
|
|
59
|
+
- id: ws_67ebcbb9ab4481918bebf63b66dbb67c04f5055a2a33abc3
|
|
60
|
+
status: completed
|
|
61
|
+
type: web_search_call
|
|
62
|
+
- content:
|
|
63
|
+
- annotations:
|
|
64
|
+
- end_index: 571
|
|
65
|
+
start_index: 404
|
|
66
|
+
title: OpenAI plans to release open-weight language model in coming months
|
|
67
|
+
type: url_citation
|
|
68
|
+
url: https://www.reuters.com/technology/artificial-intelligence/openai-plans-release-open-weight-language-model-coming-months-2025-03-31/?utm_source=openai
|
|
69
|
+
- end_index: 846
|
|
70
|
+
start_index: 625
|
|
71
|
+
title: OpenAI plans to release open-weight language model in coming months
|
|
72
|
+
type: url_citation
|
|
73
|
+
url: https://www.reuters.com/technology/artificial-intelligence/openai-plans-release-open-weight-language-model-coming-months-2025-03-31/?utm_source=openai
|
|
74
|
+
text: "In the past 24 hours, OpenAI announced plans to release its first open-weight language model with reasoning
|
|
75
|
+
capabilities since GPT-2. This model will allow developers to fine-tune it for specific applications without needing
|
|
76
|
+
the original training data. To gather feedback and refine the model, OpenAI will host developer events starting
|
|
77
|
+
in San Francisco and expanding to Europe and Asia-Pacific regions. ([reuters.com](https://www.reuters.com/technology/artificial-intelligence/openai-plans-release-open-weight-language-model-coming-months-2025-03-31/?utm_source=openai))\n\n\n##
|
|
78
|
+
OpenAI to Release Open-Weight Language Model:\n- [OpenAI plans to release open-weight language model in coming
|
|
79
|
+
months](https://www.reuters.com/technology/artificial-intelligence/openai-plans-release-open-weight-language-model-coming-months-2025-03-31/?utm_source=openai) "
|
|
80
|
+
type: output_text
|
|
81
|
+
id: msg_67ebcbbaf988819192d44919020b82e704f5055a2a33abc3
|
|
82
|
+
role: assistant
|
|
83
|
+
status: completed
|
|
84
|
+
type: message
|
|
85
|
+
parallel_tool_calls: true
|
|
86
|
+
previous_response_id: null
|
|
87
|
+
reasoning:
|
|
88
|
+
effort: null
|
|
89
|
+
generate_summary: null
|
|
90
|
+
status: completed
|
|
91
|
+
store: true
|
|
92
|
+
temperature: 1.0
|
|
93
|
+
text:
|
|
94
|
+
format:
|
|
95
|
+
type: text
|
|
96
|
+
tool_choice: auto
|
|
97
|
+
tools:
|
|
98
|
+
- search_context_size: medium
|
|
99
|
+
type: web_search_preview
|
|
100
|
+
user_location:
|
|
101
|
+
city: null
|
|
102
|
+
country: US
|
|
103
|
+
region: null
|
|
104
|
+
timezone: null
|
|
105
|
+
type: approximate
|
|
106
|
+
top_p: 1.0
|
|
107
|
+
truncation: disabled
|
|
108
|
+
usage:
|
|
109
|
+
input_tokens: 320
|
|
110
|
+
input_tokens_details:
|
|
111
|
+
cached_tokens: 0
|
|
112
|
+
output_tokens: 200
|
|
113
|
+
output_tokens_details:
|
|
114
|
+
reasoning_tokens: 0
|
|
115
|
+
total_tokens: 520
|
|
116
|
+
user: null
|
|
117
|
+
status:
|
|
118
|
+
code: 200
|
|
119
|
+
message: OK
|
|
120
|
+
version: 1
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
interactions:
|
|
2
|
+
- request:
|
|
3
|
+
headers:
|
|
4
|
+
accept:
|
|
5
|
+
- application/json
|
|
6
|
+
accept-encoding:
|
|
7
|
+
- gzip, deflate
|
|
8
|
+
connection:
|
|
9
|
+
- keep-alive
|
|
10
|
+
content-length:
|
|
11
|
+
- '218'
|
|
12
|
+
content-type:
|
|
13
|
+
- application/json
|
|
14
|
+
host:
|
|
15
|
+
- api.openai.com
|
|
16
|
+
method: POST
|
|
17
|
+
parsed_body:
|
|
18
|
+
input:
|
|
19
|
+
- content: What should I do to cross the street?
|
|
20
|
+
role: user
|
|
21
|
+
instructions: ''
|
|
22
|
+
model: computer-use-preview
|
|
23
|
+
reasoning:
|
|
24
|
+
effort: null
|
|
25
|
+
generate_summary: concise
|
|
26
|
+
stream: false
|
|
27
|
+
truncation: auto
|
|
28
|
+
uri: https://api.openai.com/v1/responses
|
|
29
|
+
response:
|
|
30
|
+
headers:
|
|
31
|
+
alt-svc:
|
|
32
|
+
- h3=":443"; ma=86400
|
|
33
|
+
connection:
|
|
34
|
+
- keep-alive
|
|
35
|
+
content-length:
|
|
36
|
+
- '1976'
|
|
37
|
+
content-type:
|
|
38
|
+
- application/json
|
|
39
|
+
openai-organization:
|
|
40
|
+
- pydantic-28gund
|
|
41
|
+
openai-processing-ms:
|
|
42
|
+
- '2793'
|
|
43
|
+
openai-version:
|
|
44
|
+
- '2020-10-01'
|
|
45
|
+
strict-transport-security:
|
|
46
|
+
- max-age=31536000; includeSubDomains; preload
|
|
47
|
+
transfer-encoding:
|
|
48
|
+
- chunked
|
|
49
|
+
parsed_body:
|
|
50
|
+
created_at: 1743514924
|
|
51
|
+
error: null
|
|
52
|
+
id: resp_67ebed2c92cc81919d2fe37992a6a78b0e0766e7260ad9b9
|
|
53
|
+
incomplete_details: null
|
|
54
|
+
instructions: ''
|
|
55
|
+
max_output_tokens: null
|
|
56
|
+
metadata: {}
|
|
57
|
+
model: computer-use-preview-2025-03-11
|
|
58
|
+
object: response
|
|
59
|
+
output:
|
|
60
|
+
- content:
|
|
61
|
+
- annotations: []
|
|
62
|
+
text: |-
|
|
63
|
+
To cross the street safely, follow these steps:
|
|
64
|
+
|
|
65
|
+
1. **Use a Crosswalk**: Always use a designated crosswalk or pedestrian crossing whenever available.
|
|
66
|
+
2. **Press the Button**: If there is a pedestrian signal button, press it and wait for the signal.
|
|
67
|
+
3. **Look Both Ways**: Look left, right, and left again before stepping off the curb.
|
|
68
|
+
4. **Wait for the Signal**: Cross only when the pedestrian signal indicates it is safe to do so or when there is a clear gap in traffic.
|
|
69
|
+
5. **Stay Alert**: Be mindful of turning vehicles and stay attentive while crossing.
|
|
70
|
+
6. **Walk, Don't Run**: Walk across the street; running can increase the risk of falling or not noticing an oncoming vehicle.
|
|
71
|
+
|
|
72
|
+
Always follow local traffic rules and be cautious, even when crossing at a crosswalk. Safety is the priority.
|
|
73
|
+
type: output_text
|
|
74
|
+
id: msg_67ebed2db814819195e77f3dd1f057640e0766e7260ad9b9
|
|
75
|
+
role: assistant
|
|
76
|
+
status: completed
|
|
77
|
+
type: message
|
|
78
|
+
parallel_tool_calls: true
|
|
79
|
+
previous_response_id: null
|
|
80
|
+
reasoning:
|
|
81
|
+
effort: medium
|
|
82
|
+
generate_summary: concise
|
|
83
|
+
status: completed
|
|
84
|
+
store: true
|
|
85
|
+
temperature: 1.0
|
|
86
|
+
text:
|
|
87
|
+
format:
|
|
88
|
+
type: text
|
|
89
|
+
tool_choice: auto
|
|
90
|
+
tools: []
|
|
91
|
+
top_p: 1.0
|
|
92
|
+
truncation: auto
|
|
93
|
+
usage:
|
|
94
|
+
input_tokens: 15
|
|
95
|
+
input_tokens_details:
|
|
96
|
+
cached_tokens: 0
|
|
97
|
+
output_tokens: 180
|
|
98
|
+
output_tokens_details:
|
|
99
|
+
reasoning_tokens: 0
|
|
100
|
+
total_tokens: 195
|
|
101
|
+
user: null
|
|
102
|
+
status:
|
|
103
|
+
code: 200
|
|
104
|
+
message: OK
|
|
105
|
+
version: 1
|
|
@@ -566,11 +566,9 @@ async def test_image_url_input(allow_model_requests: None, anthropic_api_key: st
|
|
|
566
566
|
ImageUrl(url='https://t3.ftcdn.net/jpg/00/85/79/92/360_F_85799278_0BBGV9OAdQDTLnKwAPBCcg1J7QtiieJY.jpg'),
|
|
567
567
|
]
|
|
568
568
|
)
|
|
569
|
-
assert result.data == snapshot(
|
|
570
|
-
This is a potato. It's a yellow-
|
|
571
|
-
|
|
572
|
-
Potatoes are root vegetables that are staple foods in many cuisines around the world. They can be prepared in numerous ways such as boiling, baking, roasting, frying, or mashing. This particular potato looks like it could be a Yukon Gold or a similar yellow-fleshed variety.\
|
|
573
|
-
""")
|
|
569
|
+
assert result.data == snapshot(
|
|
570
|
+
"This is a potato. It's a yellow-brown, oblong-shaped potato with a smooth skin and some small eyes or blemishes visible on its surface. Potatoes are starchy root vegetables that are a staple food in many cuisines around the world. They can be prepared in numerous ways, such as boiling, baking, frying, or mashing, and are rich in carbohydrates and nutrients."
|
|
571
|
+
)
|
|
574
572
|
|
|
575
573
|
|
|
576
574
|
@pytest.mark.vcr()
|
|
@@ -639,11 +637,11 @@ async def test_document_url_input(allow_model_requests: None, anthropic_api_key:
|
|
|
639
637
|
m = AnthropicModel('claude-3-5-sonnet-latest', provider=AnthropicProvider(api_key=anthropic_api_key))
|
|
640
638
|
agent = Agent(m)
|
|
641
639
|
|
|
642
|
-
document_url = DocumentUrl(url='https://
|
|
640
|
+
document_url = DocumentUrl(url='https://pdfobject.com/pdf/sample.pdf')
|
|
643
641
|
|
|
644
642
|
result = await agent.run(['What is the main content on this document?', document_url])
|
|
645
643
|
assert result.data == snapshot(
|
|
646
|
-
'
|
|
644
|
+
'This document appears to be a sample PDF file that primarily contains Lorem ipsum text, which is placeholder text commonly used in design and publishing. The document begins with "Sample PDF" and states "This is a simple PDF file. Fun fun fun." followed by several paragraphs of Lorem ipsum text. The content doesn\'t convey any meaningful information as Lorem ipsum is essentially dummy text used to demonstrate the visual form of a document without the distraction of meaningful content.'
|
|
647
645
|
)
|
|
648
646
|
|
|
649
647
|
|
|
@@ -22,7 +22,7 @@ from pydantic_ai.messages import (
|
|
|
22
22
|
from ..conftest import IsDatetime, IsStr, TestEnv, try_import
|
|
23
23
|
|
|
24
24
|
with try_import() as imports_successful:
|
|
25
|
-
from pydantic_ai.models.openai import OpenAIModelSettings, OpenAIResponsesModel
|
|
25
|
+
from pydantic_ai.models.openai import OpenAIModelSettings, OpenAIResponsesModel, OpenAIResponsesModelSettings
|
|
26
26
|
from pydantic_ai.providers.openai import OpenAIProvider
|
|
27
27
|
|
|
28
28
|
pytestmark = [
|
|
@@ -118,6 +118,30 @@ async def test_openai_responses_reasoning_effort(allow_model_requests: None, ope
|
|
|
118
118
|
)
|
|
119
119
|
|
|
120
120
|
|
|
121
|
+
async def test_openai_responses_reasoning_generate_summary(allow_model_requests: None, openai_api_key: str):
|
|
122
|
+
model = OpenAIResponsesModel('computer-use-preview', provider=OpenAIProvider(api_key=openai_api_key))
|
|
123
|
+
agent = Agent(
|
|
124
|
+
model=model,
|
|
125
|
+
model_settings=OpenAIResponsesModelSettings(
|
|
126
|
+
openai_reasoning_generate_summary='concise',
|
|
127
|
+
openai_truncation='auto',
|
|
128
|
+
),
|
|
129
|
+
)
|
|
130
|
+
result = await agent.run('What should I do to cross the street?')
|
|
131
|
+
assert result.data == snapshot("""\
|
|
132
|
+
To cross the street safely, follow these steps:
|
|
133
|
+
|
|
134
|
+
1. **Use a Crosswalk**: Always use a designated crosswalk or pedestrian crossing whenever available.
|
|
135
|
+
2. **Press the Button**: If there is a pedestrian signal button, press it and wait for the signal.
|
|
136
|
+
3. **Look Both Ways**: Look left, right, and left again before stepping off the curb.
|
|
137
|
+
4. **Wait for the Signal**: Cross only when the pedestrian signal indicates it is safe to do so or when there is a clear gap in traffic.
|
|
138
|
+
5. **Stay Alert**: Be mindful of turning vehicles and stay attentive while crossing.
|
|
139
|
+
6. **Walk, Don't Run**: Walk across the street; running can increase the risk of falling or not noticing an oncoming vehicle.
|
|
140
|
+
|
|
141
|
+
Always follow local traffic rules and be cautious, even when crossing at a crosswalk. Safety is the priority.\
|
|
142
|
+
""")
|
|
143
|
+
|
|
144
|
+
|
|
121
145
|
async def test_openai_responses_system_prompt(allow_model_requests: None, openai_api_key: str):
|
|
122
146
|
model = OpenAIResponsesModel('gpt-4o', provider=OpenAIProvider(api_key=openai_api_key))
|
|
123
147
|
agent = Agent(model=model, system_prompt='You are a helpful assistant.')
|
|
@@ -286,3 +310,39 @@ async def test_openai_responses_model_http_error(allow_model_requests: None, ope
|
|
|
286
310
|
with pytest.raises(ModelHTTPError):
|
|
287
311
|
async with agent.run_stream('What is the capital of France?'):
|
|
288
312
|
...
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
async def test_openai_responses_model_builtin_tools(allow_model_requests: None, openai_api_key: str):
|
|
316
|
+
model = OpenAIResponsesModel('gpt-4o', provider=OpenAIProvider(api_key=openai_api_key))
|
|
317
|
+
settings = OpenAIResponsesModelSettings(openai_builtin_tools=[{'type': 'web_search_preview'}])
|
|
318
|
+
agent = Agent(model=model, model_settings=settings)
|
|
319
|
+
result = await agent.run('Give me the best news about LLMs from the last 24 hours. Be short.')
|
|
320
|
+
|
|
321
|
+
# NOTE: We don't have the tool call because OpenAI calls the tool internally.
|
|
322
|
+
assert result.all_messages() == snapshot(
|
|
323
|
+
[
|
|
324
|
+
ModelRequest(
|
|
325
|
+
parts=[
|
|
326
|
+
UserPromptPart(
|
|
327
|
+
content='Give me the best news about LLMs from the last 24 hours. Be short.',
|
|
328
|
+
timestamp=IsDatetime(),
|
|
329
|
+
)
|
|
330
|
+
]
|
|
331
|
+
),
|
|
332
|
+
ModelResponse(
|
|
333
|
+
parts=[
|
|
334
|
+
TextPart(
|
|
335
|
+
content="""\
|
|
336
|
+
In the past 24 hours, OpenAI announced plans to release its first open-weight language model with reasoning capabilities since GPT-2. This model will allow developers to fine-tune it for specific applications without needing the original training data. To gather feedback and refine the model, OpenAI will host developer events starting in San Francisco and expanding to Europe and Asia-Pacific regions. ([reuters.com](https://www.reuters.com/technology/artificial-intelligence/openai-plans-release-open-weight-language-model-coming-months-2025-03-31/?utm_source=openai))
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
## OpenAI to Release Open-Weight Language Model:
|
|
340
|
+
- [OpenAI plans to release open-weight language model in coming months](https://www.reuters.com/technology/artificial-intelligence/openai-plans-release-open-weight-language-model-coming-months-2025-03-31/?utm_source=openai) \
|
|
341
|
+
"""
|
|
342
|
+
)
|
|
343
|
+
],
|
|
344
|
+
model_name='gpt-4o-2024-08-06',
|
|
345
|
+
timestamp=IsDatetime(),
|
|
346
|
+
),
|
|
347
|
+
]
|
|
348
|
+
)
|