gooddata-eval 1.78.1.dev3__tar.gz → 1.78.1.dev4__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 (155) hide show
  1. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/PKG-INFO +2 -2
  2. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/pyproject.toml +2 -2
  3. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/agentic/document_skill.py +25 -5
  4. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/chat/sse_client.py +21 -2
  5. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/config.py +19 -0
  6. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_agentic_document_skill.py +68 -0
  7. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_sse_client.py +52 -3
  8. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/.gitignore +0 -0
  9. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/AGENTS.md +0 -0
  10. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/CLAUDE.md +0 -0
  11. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/LICENSE.txt +0 -0
  12. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/Makefile +0 -0
  13. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/README.md +0 -0
  14. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/scripts/calibrate_takeaway_judge.py +0 -0
  15. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/scripts/verify_guardrail_refusal_criteria.py +0 -0
  16. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/__init__.py +0 -0
  17. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/_version.py +0 -0
  18. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/cli/__init__.py +0 -0
  19. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/cli/agentic_runner.py +0 -0
  20. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/cli/main.py +0 -0
  21. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/__init__.py +0 -0
  22. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/_output.py +0 -0
  23. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/_retry.py +0 -0
  24. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/agentic/__init__.py +0 -0
  25. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/agentic/_catalog.py +0 -0
  26. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/agentic/_conversation_context.py +0 -0
  27. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/agentic/_failed_runs.py +0 -0
  28. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/agentic/_gate.py +0 -0
  29. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/agentic/_langfuse.py +0 -0
  30. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/agentic/_trace_linker.py +0 -0
  31. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/agentic/alert_skill.py +0 -0
  32. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/agentic/anomaly_detection.py +0 -0
  33. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/agentic/conversation.py +0 -0
  34. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/agentic/dashboard_skill.py +0 -0
  35. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/agentic/general_question.py +0 -0
  36. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/agentic/guardrail.py +0 -0
  37. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/agentic/kda_skill.py +0 -0
  38. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/agentic/metric_skill.py +0 -0
  39. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/agentic/report_skill.py +0 -0
  40. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/agentic/search_tool.py +0 -0
  41. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/agentic/visualization.py +0 -0
  42. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/agentic/what_if.py +0 -0
  43. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/chat/__init__.py +0 -0
  44. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/chat/render.py +0 -0
  45. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/connection.py +0 -0
  46. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/dataset/__init__.py +0 -0
  47. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/dataset/from_insights.py +0 -0
  48. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/dataset/langfuse_source.py +0 -0
  49. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/dataset/local.py +0 -0
  50. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/evaluators/__init__.py +0 -0
  51. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/evaluators/_deep_subset.py +0 -0
  52. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/evaluators/_guardrail_criteria.py +0 -0
  53. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/evaluators/_llm_judge.py +0 -0
  54. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/evaluators/_maql.py +0 -0
  55. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/evaluators/_rubric.py +0 -0
  56. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/evaluators/_text_utils.py +0 -0
  57. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/evaluators/alert_skill.py +0 -0
  58. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/evaluators/base.py +0 -0
  59. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/evaluators/general_question.py +0 -0
  60. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/evaluators/guardrail.py +0 -0
  61. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/evaluators/metric_skill.py +0 -0
  62. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/evaluators/search_tool.py +0 -0
  63. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/evaluators/summary.py +0 -0
  64. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/evaluators/takeaway.py +0 -0
  65. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/evaluators/visualization.py +0 -0
  66. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/granularity.py +0 -0
  67. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/interaction.py +0 -0
  68. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/langfuse/__init__.py +0 -0
  69. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/langfuse/_env.py +0 -0
  70. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/langfuse/client.py +0 -0
  71. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/langfuse/experiment.py +0 -0
  72. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/langfuse/item_scope.py +0 -0
  73. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/langfuse/observations.py +0 -0
  74. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/langfuse/otlp.py +0 -0
  75. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/langfuse/sink.py +0 -0
  76. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/models.py +0 -0
  77. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/number_format.py +0 -0
  78. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/reporting/__init__.py +0 -0
  79. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/reporting/console.py +0 -0
  80. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/reporting/html_report.py +0 -0
  81. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/reporting/json_report.py +0 -0
  82. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/reporting/report_template.html +0 -0
  83. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/runner.py +0 -0
  84. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/scoring.py +0 -0
  85. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/summary/__init__.py +0 -0
  86. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/summary/http_client.py +0 -0
  87. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/takeaway/__init__.py +0 -0
  88. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/takeaway/evaluate.py +0 -0
  89. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/takeaway/http_client.py +0 -0
  90. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/timing.py +0 -0
  91. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/src/gooddata_eval/core/workspace.py +0 -0
  92. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/__init__.py +0 -0
  93. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/_fake_langfuse.py +0 -0
  94. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/conftest.py +0 -0
  95. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/fixtures/sample_dataset/metric_skill_create.json +0 -0
  96. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/fixtures/sample_dataset/visualization_revenue.json +0 -0
  97. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/fixtures/sse_visualization_stream.txt +0 -0
  98. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/fixtures/takeaway_calibration.json +0 -0
  99. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_agentic_alert_skill.py +0 -0
  100. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_agentic_anomaly_detection.py +0 -0
  101. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_agentic_conversation.py +0 -0
  102. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_agentic_dashboard_skill.py +0 -0
  103. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_agentic_gate.py +0 -0
  104. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_agentic_general_question.py +0 -0
  105. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_agentic_guardrail.py +0 -0
  106. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_agentic_join_trace.py +0 -0
  107. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_agentic_kda_skill.py +0 -0
  108. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_agentic_langfuse_trace.py +0 -0
  109. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_agentic_metric_skill.py +0 -0
  110. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_agentic_observe_experiment.py +0 -0
  111. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_agentic_run_context.py +0 -0
  112. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_agentic_runner.py +0 -0
  113. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_agentic_search_tool.py +0 -0
  114. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_agentic_visualization.py +0 -0
  115. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_agentic_what_if.py +0 -0
  116. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_alert_skill_evaluator.py +0 -0
  117. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_chat_render.py +0 -0
  118. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_cli.py +0 -0
  119. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_connection.py +0 -0
  120. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_deep_subset.py +0 -0
  121. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_fake_langfuse.py +0 -0
  122. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_from_insights.py +0 -0
  123. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_guardrail_criteria.py +0 -0
  124. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_html_report.py +0 -0
  125. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_interaction.py +0 -0
  126. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_langfuse_client.py +0 -0
  127. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_langfuse_e2e_fake_server.py +0 -0
  128. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_langfuse_env.py +0 -0
  129. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_langfuse_experiment.py +0 -0
  130. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_langfuse_item_scope.py +0 -0
  131. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_langfuse_observations.py +0 -0
  132. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_langfuse_otlp.py +0 -0
  133. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_langfuse_sink.py +0 -0
  134. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_langfuse_source.py +0 -0
  135. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_llm_judge.py +0 -0
  136. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_local_loader.py +0 -0
  137. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_maql_normalize.py +0 -0
  138. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_metric_skill_evaluator.py +0 -0
  139. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_models.py +0 -0
  140. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_number_format.py +0 -0
  141. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_reporting.py +0 -0
  142. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_runner.py +0 -0
  143. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_scoring.py +0 -0
  144. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_search_tool_evaluator.py +0 -0
  145. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_summary_client.py +0 -0
  146. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_summary_evaluator.py +0 -0
  147. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_takeaway_client.py +0 -0
  148. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_takeaway_evaluate.py +0 -0
  149. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_takeaway_evaluator.py +0 -0
  150. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_text_evaluators.py +0 -0
  151. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_timing.py +0 -0
  152. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_trace_linker.py +0 -0
  153. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_visualization_evaluator.py +0 -0
  154. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tests/test_workspace.py +0 -0
  155. {gooddata_eval-1.78.1.dev3 → gooddata_eval-1.78.1.dev4}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: gooddata-eval
3
- Version: 1.78.1.dev3
3
+ Version: 1.78.1.dev4
4
4
  Summary: Evaluate the GoodData AI agent against your own questions and models.
5
5
  Project-URL: Source, https://github.com/gooddata/gooddata-python-sdk
6
6
  Author-email: GoodData <support@gooddata.com>
@@ -17,7 +17,7 @@ Classifier: Topic :: Scientific/Engineering
17
17
  Classifier: Topic :: Software Development
18
18
  Classifier: Typing :: Typed
19
19
  Requires-Python: >=3.10
20
- Requires-Dist: gooddata-sdk~=1.78.1.dev3
20
+ Requires-Dist: gooddata-sdk~=1.78.1.dev4
21
21
  Requires-Dist: httpx<1.0,>=0.27
22
22
  Requires-Dist: jsonpatch<2.0,>=1.33
23
23
  Requires-Dist: orjson<4.0.0,>=3.9.15
@@ -1,7 +1,7 @@
1
1
  # (C) 2026 GoodData Corporation
2
2
  [project]
3
3
  name = "gooddata-eval"
4
- version = "1.78.1.dev3"
4
+ version = "1.78.1.dev4"
5
5
  description = "Evaluate the GoodData AI agent against your own questions and models."
6
6
  readme = "README.md"
7
7
  license = "MIT"
@@ -11,7 +11,7 @@ authors = [
11
11
  keywords = ["gooddata", "ai", "evaluation", "llm", "analytics", "cli"]
12
12
  requires-python = ">=3.10"
13
13
  dependencies = [
14
- "gooddata-sdk~=1.78.1.dev3",
14
+ "gooddata-sdk~=1.78.1.dev4",
15
15
  "httpx>=0.27,<1.0",
16
16
  "jsonpatch>=1.33,<2.0",
17
17
  "orjson>=3.9.15,<4.0.0",
@@ -32,7 +32,7 @@ from gooddata_eval.core.agentic._trace_linker import (
32
32
  from gooddata_eval.core.agentic.dashboard_skill import _extract_tool_result, _skill_activated
33
33
  from gooddata_eval.core.chat.render import render_answer_text
34
34
  from gooddata_eval.core.chat.sse_client import ChatClient
35
- from gooddata_eval.core.config import ReasoningEffort
35
+ from gooddata_eval.core.config import DocumentFormat, ReasoningEffort, normalize_document_format
36
36
  from gooddata_eval.core.evaluators._llm_judge import JudgeResponseError, LLMJudge, score_run
37
37
  from gooddata_eval.core.langfuse.item_scope import item_scope
38
38
  from gooddata_eval.core.models import (
@@ -801,18 +801,24 @@ def run_agentic_document_skill(
801
801
  agent_id: str | None = None,
802
802
  judge: LLMJudge | None = None,
803
803
  user_context: dict | None = None,
804
+ document_format: DocumentFormat | None = None,
804
805
  ) -> AgenticDocumentSummary:
805
806
  """Run the document-skill agentic evaluation K times and return a summary.
806
807
 
807
808
  The narrative judge is built only for a fixture that states a ``narrative``, so an item
808
809
  without one needs neither the llm-judge extra nor ``OPENAI_API_KEY``.
809
810
 
811
+ ``document_format`` is sent on every turn of every run, see ``ChatClient``; None leaves
812
+ the format to the server's ``enablePublisherV2`` feature flag.
813
+
810
814
  Raises:
811
815
  ValueError: the fixture is unusable — see ``_validate_expectation`` and
812
- ``_validate_user_context``.
816
+ ``_validate_user_context``, or ``document_format`` is not a format gen-ai
817
+ accepts. Raised before any chat request.
813
818
  """
814
819
  _validate_expectation(expected_output)
815
820
  _validate_user_context(user_context)
821
+ document_format = normalize_document_format(document_format)
816
822
  if judge is None and _has_narrative(expected_output):
817
823
  judge = LLMJudge(_NARRATIVE_EVALUATION_STEPS)
818
824
  run_results: list[DocumentRunResult] = []
@@ -823,6 +829,7 @@ def run_agentic_document_skill(
823
829
  reasoning_effort=reasoning_effort,
824
830
  agent_id=agent_id,
825
831
  user_context=user_context,
832
+ document_format=document_format,
826
833
  )
827
834
 
828
835
  try:
@@ -882,20 +889,32 @@ def evaluate_agentic_document_skill(
882
889
  gate: EvalGate = DEFAULT_GATE,
883
890
  judge: LLMJudge | None = None,
884
891
  user_context: dict | None = None,
892
+ document_format: DocumentFormat | None = None,
885
893
  ) -> AgenticEvalOutcome:
886
894
  """Run document-skill evaluation, log to Langfuse, and raise on failure.
887
895
 
888
896
  Returns the best run's outcome on success; on failure the same values are attached to the
889
897
  raised ``DocumentSkillAssertionError`` so callers can retrieve them either way.
890
898
 
899
+ ``document_format`` (``aac-v1``/``aac-v2``) asks gen-ai for that document content format
900
+ on every turn and is recorded as ``document_format`` in the dataset-run metadata; None
901
+ leaves it to the server's ``enablePublisherV2`` feature flag.
902
+
891
903
  Raises:
892
904
  DocumentSkillAssertionError: the gate did not pass.
893
- ValueError: the fixture is unusable — see ``_validate_expectation`` and
894
- ``_validate_user_context``. Raised before any
895
- request, so it means a fixture to fix rather than a result to read.
905
+ ValueError: the fixture is unusable, see ``_validate_expectation`` and
906
+ ``_validate_user_context``. Raised before any chat request, so it means a
907
+ fixture to fix rather than a result to read. Also raised, equally before any
908
+ request, when the caller passes a ``document_format`` gen-ai does not accept.
896
909
  JudgeResponseError: the fixture states a narrative and the judge returned no readable
897
910
  verdict for any run -- an item without a result, not K failures.
898
911
  """
912
+ document_format = normalize_document_format(document_format)
913
+ if document_format is not None:
914
+ # Metadata only, not part of the run name: it tells runs apart only when their names
915
+ # already differ, so two runs that share a run_timestamp, dataset and model but not the
916
+ # format still collide on one dataset-run name.
917
+ run_metadata_extra = {**(run_metadata_extra or {}), "document_format": document_format}
899
918
  identity = RunIdentity(
900
919
  host,
901
920
  token,
@@ -921,6 +940,7 @@ def evaluate_agentic_document_skill(
921
940
  agent_id=agent_id,
922
941
  judge=judge,
923
942
  user_context=user_context,
943
+ document_format=document_format,
924
944
  )
925
945
 
926
946
  if langfuse is not None and dataset_item_id:
@@ -26,7 +26,12 @@ from urllib.parse import quote
26
26
  import httpx
27
27
 
28
28
  from gooddata_eval.core._retry import RETRYABLE_STATUS_CODES, float_env, int_env, retry_transient
29
- from gooddata_eval.core.config import ReasoningEffort, normalize_reasoning_effort
29
+ from gooddata_eval.core.config import (
30
+ DocumentFormat,
31
+ ReasoningEffort,
32
+ normalize_document_format,
33
+ normalize_reasoning_effort,
34
+ )
30
35
  from gooddata_eval.core.langfuse.item_scope import JoinedRun, baggage_entries, current_scope, mark_joined, trace_ids_for
31
36
  from gooddata_eval.core.models import ChatResult, DatasetItem
32
37
  from gooddata_eval.core.timing import note_trace_latency
@@ -460,6 +465,7 @@ class ChatClient:
460
465
  reasoning_effort: ReasoningEffort | None = None,
461
466
  agent_id: str | None = None,
462
467
  user_context: dict[str, Any] | None = None,
468
+ document_format: DocumentFormat | None = None,
463
469
  ):
464
470
  """Create a chat client bound to one workspace.
465
471
 
@@ -476,6 +482,13 @@ class ChatClient:
476
482
  back to it: a caller that changes or clears the context per message builds the
477
483
  client without one. The server grounds answers in it only while
478
484
  the ``enableAiContextSetup`` feature flag is on for the organization.
485
+
486
+ ``document_format`` (``aac-v1``/``aac-v2``) is sent as ``options.documentFormat``
487
+ on every message and selects the document content format gen-ai drafts in for
488
+ that turn. gen-ai keeps a draft in the format of the turn that wrote it and a
489
+ turn in the other format cannot continue it, so follow-up and clarification
490
+ turns carry it too. When None the key is omitted and the server picks the format
491
+ from the ``enablePublisherV2`` feature flag. Any other value raises ``ValueError``.
479
492
  """
480
493
  self._base = f"{host.rstrip('/')}/api/v1/ai/workspaces/{workspace_id}/chat/conversations"
481
494
  self._auth = {"Authorization": f"Bearer {token}", **_trace_baggage()}
@@ -494,6 +507,7 @@ class ChatClient:
494
507
  self._client = httpx.Client(timeout=http_timeout)
495
508
  self._preserve_failed = preserve_failed
496
509
  self._reasoning_effort = normalize_reasoning_effort(reasoning_effort)
510
+ self._document_format = normalize_document_format(document_format)
497
511
  self._agent_id = agent_id
498
512
  self._user_context = user_context
499
513
  # Run index of each conversation this client has sent to, in first-send order: every
@@ -531,8 +545,13 @@ class ChatClient:
531
545
  join_headers, joined = self._join_item_trace(conversation_id)
532
546
  headers = {**self._auth, "Accept": "text/event-stream", "Content-Type": "application/json", **join_headers}
533
547
  body: dict[str, Any] = {"item": {"role": "user", "content": {"type": "text", "text": question}}}
548
+ options: dict[str, str] = {}
534
549
  if self._reasoning_effort is not None:
535
- body["options"] = {"reasoningEffort": self._reasoning_effort}
550
+ options["reasoningEffort"] = self._reasoning_effort
551
+ if self._document_format is not None:
552
+ options["documentFormat"] = self._document_format
553
+ if options:
554
+ body["options"] = options
536
555
  # A per-call context overrides the client's. Only sent when there is one: gen-ai
537
556
  # accepts an explicit null, so assigning unconditionally would quietly change every
538
557
  # request that has no attachment.
@@ -33,6 +33,9 @@ def judge_model() -> str:
33
33
  ReasoningEffort = Literal["LOW", "MEDIUM", "HIGH"]
34
34
  """Effort values the AI chat endpoint accepts, uppercase as the server enum requires."""
35
35
 
36
+ DocumentFormat = Literal["aac-v1", "aac-v2"]
37
+ """Document content formats the AI chat endpoint accepts as ``options.documentFormat``."""
38
+
36
39
  EvalGate = Literal["any", "power"]
37
40
  """`any` = pass@K, `power` = pass^K. Behaviour is in core/agentic/_gate.py; the type lives here
38
41
  because putting it there would make config import the agentic package, whose __init__ imports
@@ -73,6 +76,22 @@ def normalize_reasoning_effort(value: str | None) -> ReasoningEffort | None:
73
76
  return cast("ReasoningEffort", candidate)
74
77
 
75
78
 
79
+ def normalize_document_format(value: str | None) -> DocumentFormat | None:
80
+ """Canonical document format, or None when unset.
81
+
82
+ gen-ai rejects any value outside `DocumentFormat`, so an unknown value raises here,
83
+ before a run sends its first request.
84
+ """
85
+ if value is None:
86
+ return None
87
+ candidate = value.strip().lower()
88
+ if not candidate:
89
+ return None
90
+ if candidate not in get_args(DocumentFormat):
91
+ raise ValueError(f"Invalid document format {value!r}; expected one of {', '.join(get_args(DocumentFormat))}.")
92
+ return cast("DocumentFormat", candidate)
93
+
94
+
76
95
  @dataclass
77
96
  class RunConfig:
78
97
  host: str
@@ -536,6 +536,74 @@ def test_a_user_context_with_view_report_fails_before_any_request(monkeypatch: p
536
536
  assert client.sent == []
537
537
 
538
538
 
539
+ def test_the_document_format_reaches_the_chat_client(monkeypatch: pytest.MonkeyPatch) -> None:
540
+ client = _ScriptedChatClient([_drafting_turn()])
541
+ built: list[dict[str, Any]] = []
542
+
543
+ def _build(**kwargs: Any) -> _ScriptedChatClient:
544
+ built.append(kwargs)
545
+ return client
546
+
547
+ monkeypatch.setattr(document_skill, "ChatClient", _build)
548
+ evaluate_agentic_document_skill("https://h", "tok", "ws", "Create a document", {}, document_format="aac-v2")
549
+ assert [kwargs["document_format"] for kwargs in built] == ["aac-v2"]
550
+
551
+
552
+ def test_an_unknown_document_format_fails_before_any_request(monkeypatch: pytest.MonkeyPatch) -> None:
553
+ client = _ScriptedChatClient([_drafting_turn()])
554
+ _install_client(monkeypatch, client)
555
+ with pytest.raises(ValueError, match="Invalid document format 'v2'"):
556
+ evaluate_agentic_document_skill("https://h", "tok", "ws", "Create a document", {}, document_format="v2")
557
+ assert client.created == client.sent == []
558
+
559
+
560
+ def test_an_unknown_document_format_fails_before_the_narrative_judge_is_built(
561
+ monkeypatch: pytest.MonkeyPatch,
562
+ ) -> None:
563
+ monkeypatch.delenv("OPENAI_API_KEY", raising=False)
564
+ client = _ScriptedChatClient([_drafting_turn()])
565
+ _install_client(monkeypatch, client)
566
+ with pytest.raises(ValueError, match="Invalid document format 'v2'"):
567
+ run_agentic_document_skill("https://h", "tok", "ws", "q", {"narrative": _NARRATIVE}, document_format="v2")
568
+ assert client.created == client.sent == []
569
+
570
+
571
+ @pytest.mark.parametrize(
572
+ ("document_format", "extra", "expected"),
573
+ [
574
+ ("AAC-V2", {"tags": ["ci"]}, {"tags": ["ci"], "document_format": "aac-v2"}),
575
+ (None, {"tags": ["ci"]}, {"tags": ["ci"]}),
576
+ (None, None, None),
577
+ ],
578
+ )
579
+ def test_the_document_format_is_recorded_in_the_run_metadata(
580
+ monkeypatch: pytest.MonkeyPatch,
581
+ document_format: str | None,
582
+ extra: dict[str, Any] | None,
583
+ expected: dict[str, Any] | None,
584
+ ) -> None:
585
+ _install_client(monkeypatch, _ScriptedChatClient([_drafting_turn()]))
586
+ identities: list[Any] = []
587
+ monkeypatch.setattr(
588
+ document_skill, "submit_trace_scoring", lambda _link, identity, **_kw: identities.append(identity)
589
+ )
590
+ try:
591
+ evaluate_agentic_document_skill(
592
+ "https://h",
593
+ "tok",
594
+ "ws",
595
+ "Create a document",
596
+ {},
597
+ langfuse=object(),
598
+ dataset_item_id="item-1",
599
+ run_metadata_extra=extra,
600
+ document_format=document_format,
601
+ )
602
+ except DocumentSkillAssertionError:
603
+ pass # the identity is handed to scoring before the gate raises
604
+ assert [identity.run_metadata_extra for identity in identities] == [expected]
605
+
606
+
539
607
  # ── fixture validation ──────────────────────────────────────────────────────
540
608
 
541
609
 
@@ -2,6 +2,7 @@
2
2
  import json
3
3
  import logging
4
4
  from collections.abc import Callable
5
+ from typing import Any
5
6
  from urllib.parse import unquote
6
7
 
7
8
  import httpx
@@ -951,12 +952,23 @@ def test_ask_attaches_conversation_id_to_exception(monkeypatch):
951
952
  assert ei.value.conversation_id == "conv-exc"
952
953
 
953
954
 
954
- def _capture_body_client(captured, *, reasoning_effort=None):
955
- def handler(request):
955
+ def _capture_body_client(
956
+ captured: list[dict[str, Any]],
957
+ *,
958
+ reasoning_effort: str | None = None,
959
+ document_format: str | None = None,
960
+ ) -> ChatClient:
961
+ def handler(request: httpx.Request) -> httpx.Response:
956
962
  captured.append(json.loads(request.content))
957
963
  return httpx.Response(200, content=_OK_SSE)
958
964
 
959
- client = ChatClient(host="https://example.invalid", token="t", workspace_id="w", reasoning_effort=reasoning_effort)
965
+ client = ChatClient(
966
+ host="https://example.invalid",
967
+ token="t",
968
+ workspace_id="w",
969
+ reasoning_effort=reasoning_effort,
970
+ document_format=document_format,
971
+ )
960
972
  client._client = httpx.Client(transport=httpx.MockTransport(handler))
961
973
  return client
962
974
 
@@ -1026,6 +1038,43 @@ def test_invalid_reasoning_effort_fails_at_construction():
1026
1038
  ChatClient(host="https://example.invalid", token="t", workspace_id="w", reasoning_effort="maximum")
1027
1039
 
1028
1040
 
1041
+ @pytest.mark.parametrize("document_format", ["aac-v1", "aac-v2"])
1042
+ def test_send_message_sends_document_format_on_every_message(document_format: str) -> None:
1043
+ """gen-ai keeps a draft in the format of the turn that wrote it, so follow-ups need it too."""
1044
+ captured: list[dict[str, Any]] = []
1045
+ client = _capture_body_client(captured, document_format=document_format)
1046
+ client.send_message("conv", "first")
1047
+ client.send_message("conv", "follow-up")
1048
+ assert [c["options"] for c in captured] == [{"documentFormat": document_format}] * 2
1049
+
1050
+
1051
+ def test_send_message_sends_document_format_with_reasoning_effort() -> None:
1052
+ captured: list[dict[str, Any]] = []
1053
+ _capture_body_client(captured, reasoning_effort="LOW", document_format="aac-v2").send_message("conv", "q")
1054
+ assert captured[0]["options"] == {"reasoningEffort": "LOW", "documentFormat": "aac-v2"}
1055
+
1056
+
1057
+ @pytest.mark.parametrize(("given", "sent"), [("AAC-V2", "aac-v2"), (" aac-v1 ", "aac-v1")])
1058
+ def test_send_message_normalizes_document_format(given: str, sent: str) -> None:
1059
+ captured: list[dict[str, Any]] = []
1060
+ _capture_body_client(captured, document_format=given).send_message("conv", "q")
1061
+ assert captured[0]["options"] == {"documentFormat": sent}
1062
+
1063
+
1064
+ @pytest.mark.parametrize("blank", ["", " "])
1065
+ def test_blank_document_format_is_treated_as_unset(blank: str) -> None:
1066
+ captured: list[dict[str, Any]] = []
1067
+ _capture_body_client(captured, document_format=blank).send_message("conv", "q")
1068
+ assert "options" not in captured[0]
1069
+
1070
+
1071
+ @pytest.mark.parametrize("bad", ["v2", "aac-v3", "aac_v2"])
1072
+ def test_invalid_document_format_fails_at_construction(bad: str) -> None:
1073
+ """gen-ai rejects any other value; fail before the first request instead."""
1074
+ with pytest.raises(ValueError, match="Invalid document format"):
1075
+ ChatClient(host="https://example.invalid", token="t", workspace_id="w", document_format=bad)
1076
+
1077
+
1029
1078
  def test_turn_timeout_aborts_a_streaming_turn_and_is_not_retried(monkeypatch):
1030
1079
  """A chatty-but-slow agent must be cut off: httpx's per-read timeout never fires
1031
1080
  for one, so only the wall-clock budget bounds the item."""