simpleaudit 0.3.1__tar.gz → 0.3.2__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.
Files changed (125) hide show
  1. {simpleaudit-0.3.1/simpleaudit.egg-info → simpleaudit-0.3.2}/PKG-INFO +1 -1
  2. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/pyproject.toml +1 -1
  3. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/targets/model.py +14 -0
  4. {simpleaudit-0.3.1 → simpleaudit-0.3.2/simpleaudit.egg-info}/PKG-INFO +1 -1
  5. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/tests/test_targets.py +69 -0
  6. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/tests/test_tracing.py +20 -0
  7. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/LICENSE +0 -0
  8. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/README.md +0 -0
  9. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/setup.cfg +0 -0
  10. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/__init__.py +0 -0
  11. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/auditor.py +0 -0
  12. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/checklist.py +0 -0
  13. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/cli.py +0 -0
  14. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/context_marks.py +0 -0
  15. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/cross_judge.py +0 -0
  16. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/experiment.py +0 -0
  17. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/judges/__init__.py +0 -0
  18. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/judges/abstention.py +0 -0
  19. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/judges/binary_abstention.py +0 -0
  20. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/judges/checklist.py +0 -0
  21. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/judges/compose.py +0 -0
  22. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/judges/default.py +0 -0
  23. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/judges/factuality.py +0 -0
  24. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/judges/harm.py +0 -0
  25. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/judges/helpfulness.py +0 -0
  26. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/judges/helsedir_sexhealth_no.py +0 -0
  27. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/judges/helsedir_sexhealth_no_rag.py +0 -0
  28. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/judges/safety.py +0 -0
  29. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/model_auditor.py +0 -0
  30. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/perturbations.py +0 -0
  31. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/reframing.py +0 -0
  32. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/repeated_results.py +0 -0
  33. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/results.py +0 -0
  34. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/scenarios/__init__.py +0 -0
  35. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/scenarios/arbeidstilsynet_arbeidstid.py +0 -0
  36. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/scenarios/bullshitbench_health.py +0 -0
  37. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/scenarios/bullshitbench_v1_v2.py +0 -0
  38. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/scenarios/health.py +0 -0
  39. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/scenarios/hei_refusal.py +0 -0
  40. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/scenarios/helfo.py +0 -0
  41. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/scenarios/helpmed.py +0 -0
  42. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/scenarios/human_rights_education.py +0 -0
  43. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/scenarios/human_rights_fair_trial.py +0 -0
  44. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/scenarios/human_rights_water.py +0 -0
  45. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/scenarios/images/blank_chart.png +0 -0
  46. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/scenarios/images/illegible_label.png +0 -0
  47. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/scenarios/images/injection.png +0 -0
  48. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/scenarios/images/make_images.py +0 -0
  49. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/scenarios/images/product_a.png +0 -0
  50. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/scenarios/images/product_b.png +0 -0
  51. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/scenarios/images/quarterly_revenue.png +0 -0
  52. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/scenarios/images/truncated_axis.png +0 -0
  53. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/scenarios/lanekassen.py +0 -0
  54. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/scenarios/nav_aap.py +0 -0
  55. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/scenarios/nb_kryss_ordning.py +0 -0
  56. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/scenarios/rag.py +0 -0
  57. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/scenarios/safety.py +0 -0
  58. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/scenarios/skatteetaten.py +0 -0
  59. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/scenarios/skatteetaten_legitimasjon.py +0 -0
  60. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/scenarios/system_prompt.py +0 -0
  61. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/scenarios/toll_reisegodskvote.py +0 -0
  62. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/scenarios/ung.py +0 -0
  63. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/scenarios/vision_integrity.py +0 -0
  64. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/spans.py +0 -0
  65. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/stats.py +0 -0
  66. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/targets/__init__.py +0 -0
  67. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/targets/base.py +0 -0
  68. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/targets/callable.py +0 -0
  69. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/targets/http.py +0 -0
  70. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/tracing/__init__.py +0 -0
  71. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/tracing/auth.py +0 -0
  72. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/tracing/context.py +0 -0
  73. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/tracing/otlp.py +0 -0
  74. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/tracing/provider.py +0 -0
  75. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/tracing/selection.py +0 -0
  76. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/tracing/shared.py +0 -0
  77. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/tracing/store.py +0 -0
  78. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/utils.py +0 -0
  79. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/visualization/scenario_viewer.html +0 -0
  80. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/visualization/server.py +0 -0
  81. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/visualization/thumbnail.png +0 -0
  82. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit/visualization/visualizer.html +0 -0
  83. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit.egg-info/SOURCES.txt +0 -0
  84. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit.egg-info/dependency_links.txt +0 -0
  85. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit.egg-info/entry_points.txt +0 -0
  86. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit.egg-info/requires.txt +0 -0
  87. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/simpleaudit.egg-info/top_level.txt +0 -0
  88. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/tests/test_anthropic_judge_default_path.py +0 -0
  89. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/tests/test_audit_flow.py +0 -0
  90. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/tests/test_basic.py +0 -0
  91. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/tests/test_checklist.py +0 -0
  92. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/tests/test_checklist_judge.py +0 -0
  93. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/tests/test_checklist_pipeline.py +0 -0
  94. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/tests/test_checklist_reframing.py +0 -0
  95. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/tests/test_cross_judge.py +0 -0
  96. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/tests/test_custom_prompts.py +0 -0
  97. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/tests/test_document_expansion.py +0 -0
  98. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/tests/test_experiment_streaming.py +0 -0
  99. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/tests/test_fakes.py +0 -0
  100. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/tests/test_file_uri.py +0 -0
  101. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/tests/test_fragility.py +0 -0
  102. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/tests/test_generation_params.py +0 -0
  103. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/tests/test_json_format.py +0 -0
  104. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/tests/test_judge_compose.py +0 -0
  105. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/tests/test_judge_notes.py +0 -0
  106. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/tests/test_judge_output_contract.py +0 -0
  107. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/tests/test_judge_postprocess.py +0 -0
  108. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/tests/test_judge_registry.py +0 -0
  109. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/tests/test_judge_response_schema.py +0 -0
  110. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/tests/test_judge_robustness_pipeline.py +0 -0
  111. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/tests/test_model_auditor.py +0 -0
  112. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/tests/test_perturbations.py +0 -0
  113. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/tests/test_reframing.py +0 -0
  114. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/tests/test_rejudge.py +0 -0
  115. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/tests/test_repeated_experiments.py +0 -0
  116. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/tests/test_resumable_experiments.py +0 -0
  117. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/tests/test_scenario_data.py +0 -0
  118. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/tests/test_scenario_pack_conventions.py +0 -0
  119. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/tests/test_spans.py +0 -0
  120. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/tests/test_stats.py +0 -0
  121. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/tests/test_strip_thinking.py +0 -0
  122. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/tests/test_target_api_key.py +0 -0
  123. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/tests/test_token_counting.py +0 -0
  124. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/tests/test_tracing_auth.py +0 -0
  125. {simpleaudit-0.3.1 → simpleaudit-0.3.2}/tests/test_vision_integrity_pack.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: simpleaudit
3
- Version: 0.3.1
3
+ Version: 0.3.2
4
4
  Summary: Lightweight AI Safety Auditing Framework
5
5
  Author: SimpleAudit Contributors
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "simpleaudit"
7
- version = "0.3.1"
7
+ version = "0.3.2"
8
8
  description = "Lightweight AI Safety Auditing Framework"
9
9
  readme = "README.md"
10
10
  license = {text = "MIT"}
@@ -88,6 +88,7 @@ class ModelTarget:
88
88
  documents=documents,
89
89
  response_format=response_format,
90
90
  params=params,
91
+ context=context,
91
92
  max_retries=self.max_retries,
92
93
  retry_backoff=self.retry_backoff,
93
94
  )
@@ -104,6 +105,7 @@ async def _client_send(
104
105
  documents: Optional[List[Union[str, Dict[str, Any]]]],
105
106
  response_format: Optional[Dict[str, Any]],
106
107
  params: Optional[Dict[str, Any]],
108
+ context: Optional[TargetContext] = None,
107
109
  max_retries: int,
108
110
  retry_backoff: float,
109
111
  ) -> TargetResponse:
@@ -111,9 +113,21 @@ async def _client_send(
111
113
 
112
114
  Imported lazily so that ``simpleaudit.targets`` does not create an import
113
115
  cycle with ``model_auditor`` at package import time.
116
+
117
+ When the per-turn context carries W3C trace headers (e.g. the engine's
118
+ scenario traceparent), they are merged into ``extra_headers`` so the
119
+ target's outgoing call propagates the trace context. This is what lets an
120
+ instrumented target export spans under the same trace id the engine's
121
+ TraceCorrelation records. User-supplied extra_headers are preserved.
114
122
  """
115
123
  from ..model_auditor import ModelAuditor
116
124
 
125
+ if context is not None and context.trace_headers:
126
+ headers = dict(params.get("extra_headers", {}) if params else {})
127
+ headers.update(context.trace_headers)
128
+ params = dict(params or {})
129
+ params["extra_headers"] = headers
130
+
117
131
  content, input_tokens, output_tokens = await ModelAuditor._call_async(
118
132
  client,
119
133
  model,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: simpleaudit
3
- Version: 0.3.1
3
+ Version: 0.3.2
4
4
  Summary: Lightweight AI Safety Auditing Framework
5
5
  Author: SimpleAudit Contributors
6
6
  License: MIT
@@ -75,6 +75,40 @@ async def test_model_target_client_mode():
75
75
  assert client.calls[0]["model"] == "m"
76
76
 
77
77
 
78
+ @pytest.mark.asyncio
79
+ async def test_model_target_client_mode_forwards_trace_headers():
80
+ """trace_headers on the per-turn context reach the wire as extra_headers."""
81
+ client = _FakeClient()
82
+ t = ModelTarget(client=client, model="m")
83
+ ctx = TargetContext(trace_headers={"traceparent": "00-11223344556677889900112233445566-abcdef0123456789-01"})
84
+ await t.send(user="hi", context=ctx)
85
+ assert client.calls[0]["extra_headers"] == {
86
+ "traceparent": "00-11223344556677889900112233445566-abcdef0123456789-01"
87
+ }
88
+
89
+
90
+ @pytest.mark.asyncio
91
+ async def test_model_target_trace_headers_merge_with_user_params():
92
+ """User-supplied extra_headers and the framework's trace headers coexist."""
93
+ client = _FakeClient()
94
+ t = ModelTarget(client=client, model="m")
95
+ ctx = TargetContext(trace_headers={"traceparent": "00-11223344556677889900112233445566-abcdef0123456789-01"})
96
+ await t.send(user="hi", params={"extra_headers": {"X-Custom": "1"}}, context=ctx)
97
+ assert client.calls[0]["extra_headers"] == {
98
+ "X-Custom": "1",
99
+ "traceparent": "00-11223344556677889900112233445566-abcdef0123456789-01",
100
+ }
101
+
102
+
103
+ @pytest.mark.asyncio
104
+ async def test_model_target_no_context_no_extra_headers():
105
+ """Without a context the call is byte-identical to the legacy path."""
106
+ client = _FakeClient()
107
+ t = ModelTarget(client=client, model="m")
108
+ await t.send(user="hi")
109
+ assert "extra_headers" not in client.calls[0]
110
+
111
+
78
112
  @pytest.mark.asyncio
79
113
  async def test_model_target_transport_mode():
80
114
  async def transport(**kw):
@@ -324,3 +358,38 @@ def test_engine_forwards_traceparent_and_records_correlation():
324
358
  assert parts[3] == "01"
325
359
  # The correlation recorded at least one turn -> trace link.
326
360
  assert correlation.all_trace_ids()
361
+
362
+
363
+ def test_engine_traceparent_reaches_wire_on_default_target():
364
+ """With the default ModelTarget (no override), the scenario's traceparent
365
+ is forwarded on the target's outgoing acompletion as extra_headers."""
366
+ import asyncio
367
+
368
+ from simpleaudit.tracing.context import TraceCorrelation
369
+ from tests.fakes import fixed_probe_auditor, fixed_severity_judge, make_auditor
370
+
371
+ client = _FakeClient()
372
+ auditor = make_auditor(
373
+ target=client,
374
+ judge=fixed_severity_judge("pass"),
375
+ auditor=fixed_probe_auditor("probe"),
376
+ max_turns=2,
377
+ show_progress=False,
378
+ )
379
+
380
+ correlation = TraceCorrelation(audit_run_id="audit_test")
381
+ scenarios = [{"name": "Wire", "description": "wire traceparent test"}]
382
+ asyncio.run(
383
+ auditor.run_async(
384
+ scenarios=scenarios,
385
+ max_turns=2,
386
+ audit_run_id="audit_test",
387
+ trace_correlation=correlation,
388
+ )
389
+ )
390
+
391
+ assert client.calls
392
+ last = client.calls[-1]
393
+ tp = last["extra_headers"]["traceparent"]
394
+ # Same trace id the correlation recorded, not a fresh unrelated one.
395
+ assert tp.split("-")[1] in correlation.all_trace_ids()
@@ -422,6 +422,26 @@ def test_parse_otlp_json_string_body():
422
422
  assert len(spans) == 1
423
423
 
424
424
 
425
+ def test_parse_otlp_json_preserves_genai_content_attributes():
426
+ payload = _otlp_http_payload()
427
+ payload["resourceSpans"][0]["scopeSpans"][0]["spans"][0]["attributes"].extend(
428
+ [
429
+ {"key": "gen_ai.input.messages", "value": {"stringValue": "user prompt"}},
430
+ {"key": "gen_ai.output.messages", "value": {"stringValue": "assistant output"}},
431
+ {"key": "gen_ai.tool.call.arguments", "value": {"stringValue": '{"x":1}'}},
432
+ {
433
+ "key": "gen_ai.retrieval.documents",
434
+ "value": {"arrayValue": {"values": [{"stringValue": "document text"}]}},
435
+ },
436
+ ]
437
+ )
438
+ span = parse_otlp_json(payload)[0]
439
+ assert span["attributes"]["gen_ai.input.messages"] == "user prompt"
440
+ assert span["attributes"]["gen_ai.output.messages"] == "assistant output"
441
+ assert span["attributes"]["gen_ai.tool.call.arguments"] == '{"x":1}'
442
+ assert span["attributes"]["gen_ai.retrieval.documents"] == ["document text"]
443
+
444
+
425
445
  @pytest.mark.asyncio
426
446
  async def test_otlp_receiver_ingests():
427
447
  receiver = OTLPTraceReceiver()
File without changes
File without changes
File without changes