whatap-python 2.2.2__tar.gz → 2.3.0__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.
- {whatap_python-2.2.2 → whatap_python-2.3.0}/PKG-INFO +1 -1
- {whatap_python-2.2.2/whatap/agent/linux/arm64 → whatap_python-2.3.0/whatap/agent/darwin/amd64}/whatap_python +0 -0
- whatap_python-2.3.0/whatap/agent/darwin/arm64/whatap_python +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/agent/linux/amd64/whatap_python +0 -0
- {whatap_python-2.2.2/whatap/agent/darwin/amd64 → whatap_python-2.3.0/whatap/agent/linux/arm64}/whatap_python +0 -0
- whatap_python-2.2.2/whatap/agent/darwin/arm64/whatap_python → whatap_python-2.3.0/whatap/agent/windows/whatap_python.exe +0 -0
- whatap_python-2.3.0/whatap/build.py +4 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/conf/configuration.py +31 -11
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/counter/tasks/llm_evaluator_task.py +66 -98
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/counter/tasks/llm_log_sink_task.py +23 -34
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/doctor.py +13 -6
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/api/prompt_meta.py +0 -1
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/evaluators/base.py +6 -3
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/evaluators/builtins/__init__.py +5 -1
- whatap_python-2.3.0/whatap/llm/evaluators/builtins/judge_factories.py +323 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/evaluators/builtins/llm_judge.py +68 -5
- whatap_python-2.3.0/whatap/llm/evaluators/hooks.py +182 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/evaluators/registry.py +38 -6
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/log_sink_packs/__init__.py +2 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/log_sink_packs/llm_step_status.py +4 -4
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/providers/bedrock/runtime.py +9 -1
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/providers/interceptor.py +17 -39
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/stats/__init__.py +4 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/skills/whatap-python-install/references/llm-evaluation.md +60 -3
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/trace_handler.py +19 -5
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap_python.egg-info/PKG-INFO +1 -1
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap_python.egg-info/SOURCES.txt +1 -0
- whatap_python-2.2.2/whatap/agent/windows/whatap_python.exe +0 -0
- whatap_python-2.2.2/whatap/build.py +0 -4
- whatap_python-2.2.2/whatap/llm/evaluators/builtins/judge_factories.py +0 -90
- {whatap_python-2.2.2 → whatap_python-2.3.0}/README.md +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/pyproject.toml +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/setup.cfg +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/setup.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/LICENSE +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/README.rst +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/__init__.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/__main__.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/bootstrap/__init__.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/bootstrap/sitecustomize.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/conf/__init__.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/conf/configure.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/conf/license.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/control/__init__.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/counter/__init__.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/counter/counter_manager.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/counter/tasks/__init__.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/counter/tasks/base_task.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/counter/tasks/llm_stat_task.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/counter/tasks/openfiledescriptor.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/io/__init__.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/io/data_inputx.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/io/data_outputx.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/__init__.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/api/__init__.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/api/agent_name.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/api/session.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/api/turn.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/api/user.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/api/workflow.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/control/__init__.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/control/cut.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/control/guard.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/control/trajectory.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/definitions.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/evaluators/__init__.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/evaluators/builtins/_json_repair.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/evaluators/builtins/answer_relevance.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/evaluators/builtins/combined_judge.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/evaluators/builtins/factuality.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/evaluators/builtins/hallucination.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/evaluators/builtins/pii_leak.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/evaluators/builtins/prompt_injection.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/evaluators/builtins/toxicity.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/evaluators/builtins/url_scan.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/evaluators/sampler.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/evaluators/scope.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/features.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/instrument/__init__.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/instrument/_boundary.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/instrument/agent.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/instrument/llm_api.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/instrument/workflow.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/log_sink_packs/llm_input_message.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/log_sink_packs/llm_log_sink_pack.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/log_sink_packs/llm_output_message.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/log_sink_packs/llm_step_eval_status.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/log_sink_packs/llm_system_message.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/log_sink_packs/llm_tool_calls.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/log_sink_packs/llm_tool_results.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/log_sink_packs/llm_tx_status.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/orchestration/__init__.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/orchestration/hermes/__init__.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/orchestration/hermes/gateway.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/orchestration/hermes/kanban.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/orchestration/langgraph/__init__.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/pricing.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/providers/__init__.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/providers/anthropic/__init__.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/providers/anthropic/messages/__init__.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/providers/anthropic/messages/messages.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/providers/anthropic/messages/messages_context.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/providers/anthropic/messages/messages_extractor.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/providers/anthropic/messages/messages_stream.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/providers/bedrock/__init__.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/providers/bedrock/_content.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/providers/bedrock/converse/__init__.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/providers/bedrock/converse/converse_context.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/providers/bedrock/converse/converse_extractor.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/providers/bedrock/event_stream.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/providers/bedrock/http.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/providers/bedrock/invoke_model/__init__.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/providers/bedrock/invoke_model/invoke_model_context.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/providers/bedrock/invoke_model/invoke_model_extractor.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/providers/bedrock/step.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/providers/openai/__init__.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/providers/openai/chat/__init__.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/providers/openai/chat/chat.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/providers/openai/chat/chat_context.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/providers/openai/chat/chat_extractor.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/providers/openai/completions/__init__.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/providers/openai/completions/completions.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/providers/openai/completions/completions_context.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/providers/openai/completions/completions_extractor.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/providers/openai/content_parser.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/providers/openai/embeddings/__init__.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/providers/openai/embeddings/embeddings.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/providers/openai/embeddings/embeddings_context.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/providers/openai/embeddings/embeddings_extractor.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/providers/openai/responses/__init__.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/providers/openai/responses/responses.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/providers/openai/responses/responses_context.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/providers/openai/responses/responses_extractor.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/providers/stream_accumulator.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/providers/workflow.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/stats/active_agent_stat.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/stats/active_stat.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/stats/actx_stat.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/stats/answer_relevance_eval_stat.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/stats/api_status_stat.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/stats/base_stat.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/stats/combined_judge_eval_stat.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/stats/error_stat.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/stats/eval_stat.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/stats/factuality_eval_stat.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/stats/feature_stat.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/stats/finish_stat.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/stats/hallucination_eval_stat.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/stats/perf_stat.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/stats/pii_leak_eval_stat.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/stats/prompt_injection_eval_stat.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/stats/token_usage_stat.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/stats/toxicity_eval_stat.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/stats/traj_actx_stat.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/llm/stats/url_scan_eval_stat.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/net/__init__.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/net/async_sender.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/net/packet_enum.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/net/packet_type_enum.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/net/param_def.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/net/stackhelper.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/net/udp_session.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/net/udp_thread.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/pack/__init__.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/pack/logSinkPack.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/pack/pack.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/pack/pack_enum.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/pack/tagCountPack.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/scripts/__init__.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/skills/whatap-python-install/AGENTS.md +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/skills/whatap-python-install/INSTALL.md +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/skills/whatap-python-install/SKILL.md +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/skills/whatap-python-install/references/config-keys.md +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/skills/whatap-python-install/references/frameworks.md +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/skills/whatap-python-install/references/llm-api-usage.md +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/skills/whatap-python-install/references/llm-observability.md +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/skills/whatap-python-install/references/troubleshooting.md +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/__init__.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/__init__.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/amqp/__init__.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/amqp/kombu.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/amqp/pika.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/application/__init__.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/application/bottle.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/application/celery.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/application/cherrypy.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/application/django.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/application/django_asgi.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/application/django_py3.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/application/fastapi/__init__.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/application/fastapi/endpoint.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/application/fastapi/exception_log.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/application/fastapi/instrumentation.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/application/fastapi/scope.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/application/fastapi/transaction.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/application/flask.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/application/frappe.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/application/graphql.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/application/nameko.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/application/odoo.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/application/starlette.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/application/tornado.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/application/wsgi.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/database/__init__.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/database/cxoracle.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/database/mongo.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/database/mysql.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/database/neo4j.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/database/psycopg2.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/database/psycopg3.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/database/redis.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/database/sqlalchemy.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/database/sqlite3.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/database/util.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/email/__init__.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/email/smtp.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/hook_service_patterns.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/httpc/__init__.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/httpc/django.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/httpc/httplib.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/httpc/httpx.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/httpc/httpx2.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/httpc/requests.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/httpc/stream_end.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/httpc/urllib3.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/httpc/util.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/logging.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/pattern_targets.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/plugin.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/process/__init__.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/process/subprocess_spawn.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/standalone/__init__.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/standalone/multiple.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/standalone/single.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/thread_context.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mod/workflow_plugin.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/mtrace_env.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/patch.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/simple_trace_context.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/trace_context.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/trace_context_manager.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/trace_error.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/trace_import.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/trace/trace_module_definition.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/util/__init__.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/util/bit_util.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/util/cardinality/__init__.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/util/cardinality/hyperloglog.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/util/cardinality/murmurhash.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/util/cardinality/registerset.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/util/compare_util.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/util/date_util.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/util/debug_util.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/util/escape_literal_sql.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/util/frame_util.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/util/hash_util.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/util/hexa32.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/util/int_set.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/util/ip_util.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/util/keygen.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/util/linked_list.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/util/linked_map.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/util/metering_util.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/util/native_process.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/util/request_double_queue.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/util/request_queue.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/util/string_util.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/util/throttle_util.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/util/userid_util.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/value/__init__.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/value/blob_value.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/value/boolean_value.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/value/decimal_value.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/value/double_summary.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/value/double_value.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/value/float_array.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/value/float_value.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/value/int_array.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/value/ip4_value.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/value/list_value.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/value/long_array.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/value/long_summary.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/value/map_value.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/value/null_value.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/value/number_value.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/value/summary_value.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/value/text_array.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/value/text_hash_value.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/value/text_value.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/value/value.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/value/value_enum.py +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap/whatap.conf +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap_python.egg-info/dependency_links.txt +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap_python.egg-info/entry_points.txt +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap_python.egg-info/not-zip-safe +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap_python.egg-info/requires.txt +0 -0
- {whatap_python-2.2.2 → whatap_python-2.3.0}/whatap_python.egg-info/top_level.txt +0 -0
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -433,6 +433,8 @@ Configuration = {
|
|
|
433
433
|
# 않는다 — 줄을 지우면 재기동 전까지 마지막 값이 그대로 남아 계속 차단된다.
|
|
434
434
|
"llm_blocked_users": "",
|
|
435
435
|
|
|
436
|
+
# >>> LLM-EVAL: 평가(Evaluation) 설정 키 — 평가 기능을 떼면 이 블록째 지운다
|
|
437
|
+
# (whatap/llm/evaluators/REMOVAL.md).
|
|
436
438
|
# ── LLM Evaluation ──
|
|
437
439
|
# 평가 파이프라인 마스터 토글. false면 enqueue/worker가 동작하지 않음.
|
|
438
440
|
"llm_eval_enabled": False,
|
|
@@ -490,26 +492,44 @@ Configuration = {
|
|
|
490
492
|
|
|
491
493
|
# ── conf 기반 default judge (앱 코드 0) ──
|
|
492
494
|
# llm-as-judge 평가자(combined_judge 등)는 평가용 LLM 호출에 자체 자격증명이 필요하다.
|
|
493
|
-
# judge 해석 순서: ① evaluator(judge_fn=) → ② set_default_judge_fn()
|
|
494
|
-
#
|
|
495
|
-
#
|
|
496
|
-
#
|
|
497
|
-
#
|
|
498
|
-
#
|
|
499
|
-
# 평가가 돈다. 코드로 set_default_judge_fn 을 이미 호출했으면 그쪽이 우선(conf 미적용).
|
|
495
|
+
# judge 해석 순서: ① evaluator(judge_fn=) → ② set_default_judge_fn() / 아래 conf →
|
|
496
|
+
# ③ 계측이 사용자 호출에서 떠 둔 엔드포인트·자격증명 스냅샷 → ④ ctx.provider 매칭 후
|
|
497
|
+
# 환경변수 키. 보통 ③ 이 자동으로 풀린다(앱과 같은 엔드포인트·자격증명·모델). OAuth 라
|
|
498
|
+
# 평문 키가 없거나 다른 모델·엔드포인트로 평가하려면 아래 키를 채운다 — 부트스트랩이 그
|
|
499
|
+
# 값으로 default judge 를 자동 등록해 앱 코드 수정 없이 conf 만으로 평가가 돈다.
|
|
500
|
+
# 코드로 set_default_judge_fn 을 이미 호출했으면 그쪽이 우선(conf 미적용).
|
|
500
501
|
#
|
|
501
|
-
#
|
|
502
|
-
#
|
|
502
|
+
# Bedrock: Bedrock 을 부르는 앱(boto3·aioboto3·AnthropicBedrock·LiteLLM)은 ③ 으로
|
|
503
|
+
# judge 도 Bedrock Runtime(Converse)으로 간다 — 앱과 같은 리전·엔드포인트·자격증명·모델.
|
|
504
|
+
# 다른 앱(OpenAI 등)도 judge 만 Bedrock 으로 보내려면 provider=bedrock + model(+region).
|
|
505
|
+
#
|
|
506
|
+
# llm_eval_judge_provider : "openai" | "anthropic" | "bedrock". 미지정 시 base_url 이
|
|
507
|
+
# 있으면 openai(호환)로 간주, 없으면 자동 등록 안 함(③/④ 유지).
|
|
503
508
|
# llm_eval_judge_model : judge 모델. 미지정 시 provider 별 default
|
|
504
|
-
# (openai=gpt-4o-mini, anthropic=claude-
|
|
509
|
+
# (openai=gpt-4o-mini, anthropic=claude-haiku-5-5).
|
|
510
|
+
# provider 나 base_url 과 함께 넣어야 적용된다 — 모델만
|
|
511
|
+
# 넣으면 무시하고 LLM056 경고(③ 은 계속 앱 모델로 평가).
|
|
512
|
+
# bedrock 은 **필수** — modelId 또는 추론 프로파일 ID
|
|
513
|
+
# (예: us.anthropic.claude-haiku-4-5-20251001-v1:0). 계정·리전마다
|
|
514
|
+
# 열린 모델이 달라 기본값을 두지 않는다.
|
|
505
515
|
# llm_eval_judge_api_key_env : judge 키가 담긴 환경변수 이름(권장 — 키를 설정 파일에
|
|
506
516
|
# 직접 두지 않음). 예: "WHATAP_LLM_EVAL_JUDGE_API_KEY".
|
|
507
517
|
# llm_eval_judge_api_key : (대안) judge API 키 직접 지정. _env 가 있으면 그쪽 우선.
|
|
508
|
-
# 로컬 vLLM 등 키가 불필요하면 "EMPTY".
|
|
518
|
+
# 로컬 vLLM 등 키가 불필요하면 "EMPTY". bedrock 엔 쓰지 않는다
|
|
519
|
+
# (AWS 자격증명으로 서명 — env / 프로파일 / IAM 역할).
|
|
509
520
|
# llm_eval_judge_base_url : (선택) OpenAI 호환 엔드포인트 / 프록시 / 내부 게이트웨이.
|
|
521
|
+
# bedrock 이면 Bedrock Runtime endpoint_url(VPC 엔드포인트 등).
|
|
522
|
+
# llm_eval_judge_region : (bedrock) AWS 리전. 미지정 시 AWS 기본 해석
|
|
523
|
+
# (AWS_DEFAULT_REGION / ~/.aws/config — botocore 는
|
|
524
|
+
# AWS_REGION 을 읽지 않는다).
|
|
525
|
+
# llm_eval_judge_aws_profile : (bedrock) ~/.aws 프로파일 이름. 미지정 시 AWS 기본 자격증명
|
|
526
|
+
# 체인(env → 공유 자격증명 파일 → IAM 역할).
|
|
510
527
|
"llm_eval_judge_provider": "",
|
|
511
528
|
"llm_eval_judge_model": "",
|
|
512
529
|
"llm_eval_judge_api_key_env": "",
|
|
513
530
|
"llm_eval_judge_api_key": "",
|
|
514
531
|
"llm_eval_judge_base_url": "",
|
|
532
|
+
"llm_eval_judge_region": "",
|
|
533
|
+
"llm_eval_judge_aws_profile": "",
|
|
534
|
+
# <<< LLM-EVAL
|
|
515
535
|
}
|
|
@@ -22,8 +22,9 @@
|
|
|
22
22
|
|
|
23
23
|
평가는 fire-and-forget. LlmStepStatus 송출과 완전 독립 — 사용자 트랜잭션 영향 0.
|
|
24
24
|
모든 예외는 swallow 후 [LLM] 로그로만 기록.
|
|
25
|
+
|
|
26
|
+
코어(계측·송출)는 이 모듈을 직접 부르지 않는다 — ``whatap.llm.evaluators.hooks`` 를 거친다.
|
|
25
27
|
"""
|
|
26
|
-
import contextvars
|
|
27
28
|
import queue
|
|
28
29
|
import threading
|
|
29
30
|
import time
|
|
@@ -32,6 +33,9 @@ from whatap import logging
|
|
|
32
33
|
from whatap.conf.configure import Configure as conf
|
|
33
34
|
|
|
34
35
|
from whatap.llm.evaluators.base import EvaluatorContext, EvaluatorResult
|
|
36
|
+
from whatap.llm.evaluators.hooks import (
|
|
37
|
+
conf_truthy as _conf_truthy, enter_judge_call, exit_judge_call, is_judge_call,
|
|
38
|
+
)
|
|
35
39
|
from whatap.llm.evaluators.registry import EvaluatorRegistry
|
|
36
40
|
from whatap.llm.evaluators.sampler import EvaluatorSampler
|
|
37
41
|
from whatap.llm.log_sink_packs.llm_step_eval_status import LlmStepEvalStatus
|
|
@@ -40,23 +44,6 @@ from whatap.llm.log_sink_packs.llm_step_eval_status import LlmStepEvalStatus
|
|
|
40
44
|
_DEFAULT_BUFFER_LIMIT = 1000
|
|
41
45
|
_DEFAULT_WORKERS = 4
|
|
42
46
|
|
|
43
|
-
|
|
44
|
-
def _conf_truthy(name, default=False):
|
|
45
|
-
"""Configure attr 을 bool 로 안전 변환.
|
|
46
|
-
|
|
47
|
-
Configure.setProperty 가 config file 에서 읽은 문자열 'true'/'false' 를 그대로
|
|
48
|
-
setattr 해서 string 으로 저장 → 'false' 도 truthy 로 평가되는 reload 버그 우회.
|
|
49
|
-
"""
|
|
50
|
-
try:
|
|
51
|
-
val = getattr(conf, name, default)
|
|
52
|
-
except Exception:
|
|
53
|
-
return bool(default)
|
|
54
|
-
if isinstance(val, bool):
|
|
55
|
-
return val
|
|
56
|
-
if isinstance(val, str):
|
|
57
|
-
return val.strip().lower() in ('true', 'yes', '1', 'on')
|
|
58
|
-
return bool(val)
|
|
59
|
-
|
|
60
47
|
_scope_ignored_warned = [False]
|
|
61
48
|
|
|
62
49
|
|
|
@@ -98,44 +85,6 @@ _LABEL_TO_FIELD = {
|
|
|
98
85
|
'combined_judge': 'eval_combined_judge',
|
|
99
86
|
}
|
|
100
87
|
|
|
101
|
-
# 평가 워커 안인지 판별하는 플래그 — 두 저장소 동시 사용:
|
|
102
|
-
# - thread-local : sync 워커 스레드 자체에서 발생한 LLM 호출 인지용
|
|
103
|
-
# - ContextVar : async judge 가 ``run_coroutine_threadsafe`` 로 user loop 에 dispatch
|
|
104
|
-
# 된 task 의 context 에서도 인지되도록 propagate
|
|
105
|
-
# 무한 재귀 방지 (judge 호출이 다시 평가 큐에 안 들어가도록) + intercept 가 judge 호출도
|
|
106
|
-
# 정상 추적 (단, 재귀 가드 덕분에 다시 평가 enqueue 되지 않음) 의 두 가지 목적.
|
|
107
|
-
_eval_worker_local = threading.local()
|
|
108
|
-
_eval_worker_cv = contextvars.ContextVar('whatap_eval_worker', default=False)
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
def _is_in_evaluator_worker():
|
|
112
|
-
"""평가 워커 안인지 — thread-local 또는 ContextVar 기준."""
|
|
113
|
-
if getattr(_eval_worker_local, 'in_eval', False):
|
|
114
|
-
return True
|
|
115
|
-
cv_val = _eval_worker_cv.get()
|
|
116
|
-
if isinstance(cv_val, dict):
|
|
117
|
-
return bool(cv_val.get('in_eval'))
|
|
118
|
-
return bool(cv_val)
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
def _get_eval_worker_state():
|
|
122
|
-
"""현재 eval worker state 반환. 없으면 None.
|
|
123
|
-
|
|
124
|
-
구조: {'in_eval', 'parent_txid', 'parent_step_id', 'parent_index'}.
|
|
125
|
-
CV 우선, fallback TL.
|
|
126
|
-
"""
|
|
127
|
-
cv_val = _eval_worker_cv.get()
|
|
128
|
-
if isinstance(cv_val, dict) and cv_val.get('in_eval'):
|
|
129
|
-
return cv_val
|
|
130
|
-
if getattr(_eval_worker_local, 'in_eval', False):
|
|
131
|
-
return {
|
|
132
|
-
'in_eval': True,
|
|
133
|
-
'parent_txid': getattr(_eval_worker_local, 'parent_txid', None),
|
|
134
|
-
'parent_step_id': getattr(_eval_worker_local, 'parent_step_id', None),
|
|
135
|
-
'parent_index': getattr(_eval_worker_local, 'parent_index', None),
|
|
136
|
-
}
|
|
137
|
-
return None
|
|
138
|
-
|
|
139
88
|
|
|
140
89
|
# EvalStat 인스턴스 캐시.
|
|
141
90
|
_eval_stat_cache = [None]
|
|
@@ -190,10 +139,12 @@ class LlmEvaluatorTask(object):
|
|
|
190
139
|
if not _conf_truthy('llm_eval_enabled'):
|
|
191
140
|
_warn_scope_ignored_once()
|
|
192
141
|
return
|
|
193
|
-
if
|
|
142
|
+
if is_judge_call():
|
|
194
143
|
return # judge 평가자의 자기 호출이 다시 평가 큐에 들어가는 무한 재귀 차단
|
|
195
144
|
if pack is None:
|
|
196
145
|
return
|
|
146
|
+
if _is_embedding_call(pack):
|
|
147
|
+
return # 평가할 텍스트 응답이 없다 — judge 가 임베딩 모델로 불려 실패만 쌓인다
|
|
197
148
|
|
|
198
149
|
# conf.llm_eval_evaluators 기반 빌트인 자동 register (1회 — 안에서 fast-path).
|
|
199
150
|
# is_empty() 검사 전에 호출해야 첫 enqueue 가 skip 안 됨.
|
|
@@ -262,27 +213,37 @@ class LlmEvaluatorTask(object):
|
|
|
262
213
|
continue
|
|
263
214
|
try:
|
|
264
215
|
merged, scope_designated = self._merge_evaluators(scope_evs)
|
|
265
|
-
|
|
266
|
-
#
|
|
267
|
-
|
|
268
|
-
#
|
|
269
|
-
# 스코프로 지정된 평가자는 샘플링 면제 (항상 실행). 구간을 지정한 것
|
|
270
|
-
# 자체가 "이 구간은 다 본다" 는 선언이고, 거기에 sample_rate 를 또
|
|
271
|
-
# 곱하면 "데코레이터 붙였는데 10% 만 평가" 가 된다.
|
|
272
|
-
active = []
|
|
273
|
-
for evaluator in merged:
|
|
274
|
-
if not evaluator.LABEL:
|
|
275
|
-
continue
|
|
276
|
-
if not scope_designated \
|
|
277
|
-
and not self._sampler.should_run(evaluator, ctx_txid):
|
|
278
|
-
continue
|
|
279
|
-
active.append(evaluator)
|
|
216
|
+
# 고른 평가자를 한 워커 task 로 묶음 — 한 LLM 호출당 LlmStepEvalStatus
|
|
217
|
+
# pack 1개만 송출되도록.
|
|
218
|
+
active = self._select_active(merged, scope_designated, pack)
|
|
280
219
|
if active:
|
|
281
220
|
self._executor.submit(self._safe_run_pack, active, pack)
|
|
282
221
|
except Exception as e:
|
|
283
222
|
logging.warning('[LLM] eval dispatch failed: %s' % e,
|
|
284
223
|
extra={'id': 'LLM031'})
|
|
285
224
|
|
|
225
|
+
def _select_active(self, evaluators, scope_designated, pack):
|
|
226
|
+
"""이 pack 에 돌릴 평가자.
|
|
227
|
+
|
|
228
|
+
- 응답 텍스트가 없는 호출(도구만 부른 단계 · 실패한 호출)은 judge 가 빈 답을 채점하게
|
|
229
|
+
되므로 judge 평가자를 건너뛴다. 규칙 기반 평가자는 그대로 돈다. 에이전트라면 최종
|
|
230
|
+
답변 단계의 입력에 앞 단계의 도구 결과가 모두 들어가므로 프롬프트 인젝션도 거기서 본다.
|
|
231
|
+
- 스코프로 지정된 평가자는 샘플링 면제 (항상 실행). 구간을 지정한 것 자체가
|
|
232
|
+
"이 구간은 다 본다" 는 선언이고, 거기에 sample_rate 를 또 곱하면 "데코레이터
|
|
233
|
+
붙였는데 10% 만 평가" 가 된다.
|
|
234
|
+
"""
|
|
235
|
+
has_response = _has_response_text(pack)
|
|
236
|
+
active = []
|
|
237
|
+
for evaluator in evaluators:
|
|
238
|
+
if not evaluator.LABEL:
|
|
239
|
+
continue
|
|
240
|
+
if not has_response and getattr(evaluator, 'USES_LLM_JUDGE', False):
|
|
241
|
+
continue
|
|
242
|
+
if not scope_designated and not self._sampler.should_run(evaluator, pack.txid):
|
|
243
|
+
continue
|
|
244
|
+
active.append(evaluator)
|
|
245
|
+
return active
|
|
246
|
+
|
|
286
247
|
@staticmethod
|
|
287
248
|
def _merge_evaluators(scope_evs=None):
|
|
288
249
|
"""이번 pack 에 실행할 평가자 목록 결정.
|
|
@@ -308,27 +269,11 @@ class LlmEvaluatorTask(object):
|
|
|
308
269
|
|
|
309
270
|
모든 예외 swallow + 재귀 방지 + 부모 step 키 propagation.
|
|
310
271
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
``llm_eval_track_judge_calls=true`` 일 때 judge LLM 호출 pack 의 결합 키를
|
|
315
|
-
user step 과 동일하게 override 해서 dashboard 에서 같은 transaction 으로
|
|
316
|
-
보이도록 함.
|
|
317
|
-
|
|
318
|
-
TL 은 워커 스레드 자체에서 발생한 LLM 호출 (sync judge), CV 는 dispatched coro
|
|
319
|
-
(async judge, user loop 으로 dispatch) 에서 propagate 되도록.
|
|
272
|
+
평가하는 동안 judge 호출 표시(``hooks.enter_judge_call``)를 켠다 — 재귀 가드이자,
|
|
273
|
+
``llm_eval_track_judge_calls=true`` 일 때 judge LLM 호출 pack 의 결합 키를 user
|
|
274
|
+
step 과 같게 덮어 dashboard 에서 같은 transaction 으로 보이게 하는 좌표.
|
|
320
275
|
"""
|
|
321
|
-
|
|
322
|
-
'in_eval': True,
|
|
323
|
-
'parent_txid': pack.txid,
|
|
324
|
-
'parent_step_id': pack.step_id,
|
|
325
|
-
'parent_index': pack.index,
|
|
326
|
-
}
|
|
327
|
-
_eval_worker_local.in_eval = True
|
|
328
|
-
_eval_worker_local.parent_txid = pack.txid
|
|
329
|
-
_eval_worker_local.parent_step_id = pack.step_id
|
|
330
|
-
_eval_worker_local.parent_index = pack.index
|
|
331
|
-
cv_token = _eval_worker_cv.set(state)
|
|
276
|
+
token = enter_judge_call(pack)
|
|
332
277
|
try:
|
|
333
278
|
self._run_pack(evaluators, pack)
|
|
334
279
|
except Exception as e:
|
|
@@ -336,11 +281,7 @@ class LlmEvaluatorTask(object):
|
|
|
336
281
|
% (len(evaluators), e),
|
|
337
282
|
extra={'id': 'LLM036'})
|
|
338
283
|
finally:
|
|
339
|
-
|
|
340
|
-
_eval_worker_local.in_eval = False
|
|
341
|
-
_eval_worker_local.parent_txid = None
|
|
342
|
-
_eval_worker_local.parent_step_id = None
|
|
343
|
-
_eval_worker_local.parent_index = None
|
|
284
|
+
exit_judge_call(token)
|
|
344
285
|
|
|
345
286
|
def _run_pack(self, evaluators, pack):
|
|
346
287
|
"""한 pack 의 모든 활성 evaluator 를 순차 실행 + 점수 모아서 단일
|
|
@@ -543,5 +484,32 @@ def build_eval_context_from_pack(pack):
|
|
|
543
484
|
event_loop=None,
|
|
544
485
|
judge_base_url=getattr(pack, '_llm_judge_base_url', None),
|
|
545
486
|
judge_api_key=getattr(pack, '_llm_judge_api_key', None),
|
|
546
|
-
judge_kind=getattr(pack, '_llm_judge_kind', None),
|
|
487
|
+
judge_kind=getattr(pack, '_llm_judge_kind', None) or _bedrock_kind(pack),
|
|
488
|
+
judge_aws=getattr(pack, '_llm_judge_aws', None),
|
|
547
489
|
)
|
|
490
|
+
|
|
491
|
+
|
|
492
|
+
def _has_response_text(pack):
|
|
493
|
+
"""judge 가 채점할 응답 텍스트가 있는가 — 도구만 부른 단계 · 실패한 호출에는 없다."""
|
|
494
|
+
return bool(str(getattr(pack, 'completion_text', '') or '').strip())
|
|
495
|
+
|
|
496
|
+
|
|
497
|
+
def _is_embedding_call(pack):
|
|
498
|
+
"""평가할 응답이 없는 임베딩 호출인가.
|
|
499
|
+
|
|
500
|
+
OpenAI 는 operation_type 이 embedding 이다. Bedrock InvokeModel 은 모델과 무관하게 chat 으로
|
|
501
|
+
분류되므로 모델 ID 로 가른다(amazon.titan-embed-* · cohere.embed-* · amazon.nova-*-embeddings-*
|
|
502
|
+
등). 텍스트 응답이 있으면 임베딩으로 보지 않는다.
|
|
503
|
+
"""
|
|
504
|
+
if str(getattr(pack, 'operation_type', '') or '').lower() == 'embedding':
|
|
505
|
+
return True
|
|
506
|
+
model = str(getattr(pack, 'model', '') or '').lower()
|
|
507
|
+
return 'embed' in model and not str(getattr(pack, 'completion_text', '') or '').strip()
|
|
508
|
+
|
|
509
|
+
|
|
510
|
+
def _bedrock_kind(pack):
|
|
511
|
+
"""스냅샷이 없는 Bedrock 호출(LiteLLM·직접 HTTP — 떠 둘 client 가 없다)도 Bedrock judge 로.
|
|
512
|
+
|
|
513
|
+
계측이 못박은 provider 키로 가른다. 리전·엔드포인트는 judge 가 호스트에서 읽는다.
|
|
514
|
+
"""
|
|
515
|
+
return 'bedrock' if getattr(pack, '_provider_key', None) == 'bedrock' else None
|
|
@@ -11,7 +11,7 @@ import whatap.io as whatapio
|
|
|
11
11
|
import whatap.net.async_sender as async_sender
|
|
12
12
|
|
|
13
13
|
# 표준 의존 방향: counter.tasks → whatap.llm. 여기서는 whatap.llm 의 **데이터 계층**
|
|
14
|
-
# (log_sink_packs) 만 모듈레벨로 import 한다. providers/
|
|
14
|
+
# (log_sink_packs) 만 모듈레벨로 import 한다. providers/stats 등 오케스트레이션
|
|
15
15
|
# 계층은 이 모듈을 (함수 스코프로) 되-import 하므로, 그쪽을 여기서 모듈레벨 import 하면
|
|
16
16
|
# 부트스트랩 순환이 된다 — 하지 말 것.
|
|
17
17
|
from whatap.llm.log_sink_packs.llm_log_sink_pack import LlmLogSinkPack, normalize_id
|
|
@@ -29,14 +29,15 @@ _MAX_CONTENT_BYTES = 20000
|
|
|
29
29
|
class LlmLogSinkTask(object):
|
|
30
30
|
"""LLM logsink pack 송출 파이프라인.
|
|
31
31
|
|
|
32
|
-
LLM 호출 결과 pack 을 받아 즉시
|
|
33
|
-
|
|
34
|
-
pack (``llm_log_type=llm_step_eval_status``) 으로 송출된다 — 원본 LlmStepStatus 와
|
|
35
|
-
동일한 fields/tags + 평가 점수 5 필드. (txid, step_id) 결합 키로 백엔드 사후 결합.
|
|
36
|
-
|
|
37
|
-
이 단순한 모델 덕분에 hold/timeout/callback 등의 복잡도가 모두 제거됨.
|
|
32
|
+
LLM 호출 결과 pack 을 받아 즉시 송출한다. 결과를 기다리는 후처리가 없으므로
|
|
33
|
+
hold/timeout/callback 등의 복잡도가 없다.
|
|
38
34
|
"""
|
|
39
35
|
|
|
36
|
+
# >>> LLM-EVAL: 평가(LLM-judge 등)는 별도 파이프라인(``LlmEvaluatorTask``)에서 비동기로 돌고,
|
|
37
|
+
# 결과는 ``LlmStepEvalStatus`` pack(``llm_log_type=llm_step_eval_status``)으로 따로 송출된다
|
|
38
|
+
# — 원본 LlmStepStatus 와 같은 fields/tags + 평가 점수. (txid, step_id) 결합 키로 백엔드 사후 결합.
|
|
39
|
+
# <<< LLM-EVAL
|
|
40
|
+
|
|
40
41
|
_instance = None
|
|
41
42
|
_lock = threading.Lock()
|
|
42
43
|
|
|
@@ -53,14 +54,7 @@ class LlmLogSinkTask(object):
|
|
|
53
54
|
return cls._instance
|
|
54
55
|
|
|
55
56
|
def dispatch(self, pack):
|
|
56
|
-
"""LLM 호출 결과 pack 을 즉시
|
|
57
|
-
|
|
58
|
-
평가 워커 안에서 호출된 judge LLM call 인 경우 (intercept 가 fire 한 케이스):
|
|
59
|
-
- operation_type='whatap_evaluation' / prompt_version='v1' 고정
|
|
60
|
-
- parent (user) step 의 (txid, step_id, index) 그대로 propagate
|
|
61
|
-
→ dashboard 에서 같은 transaction 으로 묶여 보임
|
|
62
|
-
- eval enqueue 는 재귀 가드가 자동 차단
|
|
63
|
-
"""
|
|
57
|
+
"""LLM 호출 결과 pack 을 즉시 송출한다."""
|
|
64
58
|
if not isinstance(pack, LlmStepStatus):
|
|
65
59
|
return
|
|
66
60
|
|
|
@@ -77,23 +71,15 @@ class LlmLogSinkTask(object):
|
|
|
77
71
|
% (pack.model, pack.input_tokens, pack.output_tokens, pack.cached_tokens, e),
|
|
78
72
|
extra={'id': 'LLM024'})
|
|
79
73
|
|
|
80
|
-
#
|
|
74
|
+
# >>> LLM-EVAL: judge 호출(평가 워커 안에서 난 LLM 호출)이면 고정 라벨 + 부모(사용자) 스텝
|
|
75
|
+
# 좌표로 덮는다 — 위 set_context 가 현재 컨텍스트 좌표로 되돌렸으므로 다시 덮어야 한다.
|
|
76
|
+
# 그래야 dashboard 에서 사용자 호출과 같은 transaction 으로 묶여 보인다.
|
|
81
77
|
try:
|
|
82
|
-
from whatap.
|
|
83
|
-
|
|
84
|
-
)
|
|
85
|
-
if _is_in_evaluator_worker():
|
|
86
|
-
state = _get_eval_worker_state() or {}
|
|
87
|
-
pack.operation_type = 'whatap_evaluation'
|
|
88
|
-
pack.prompt_version = 'v1'
|
|
89
|
-
if state.get('parent_txid'):
|
|
90
|
-
pack.txid = state['parent_txid']
|
|
91
|
-
if state.get('parent_step_id'):
|
|
92
|
-
pack.step_id = state['parent_step_id']
|
|
93
|
-
if state.get('parent_index') is not None:
|
|
94
|
-
pack.index = state['parent_index']
|
|
78
|
+
from whatap.llm.evaluators.hooks import mark_judge_call
|
|
79
|
+
mark_judge_call(pack)
|
|
95
80
|
except Exception:
|
|
96
81
|
pass
|
|
82
|
+
# <<< LLM-EVAL
|
|
97
83
|
|
|
98
84
|
# tx_summary 누적
|
|
99
85
|
self._accumulate_tx_summary(ctx, pack)
|
|
@@ -107,16 +93,17 @@ class LlmLogSinkTask(object):
|
|
|
107
93
|
ctx._llm_last_error_prompt_version = (
|
|
108
94
|
getattr(pack, 'prompt_version', 'v1') or 'v1')
|
|
109
95
|
|
|
110
|
-
# pack 즉시 송출
|
|
96
|
+
# pack 즉시 송출
|
|
111
97
|
self._enqueue_for_send(pack)
|
|
112
98
|
|
|
113
|
-
# 평가 큐
|
|
114
|
-
#
|
|
99
|
+
# >>> LLM-EVAL: 평가 큐 투입 — 워커가 pack 을 복제해 점수를 채워 LlmStepEvalStatus 로 송출.
|
|
100
|
+
# 원본 송출(위)은 평가 결과를 기다리지 않는다. judge 호출 자체는 재귀 가드가 걸러낸다.
|
|
115
101
|
try:
|
|
116
|
-
from whatap.
|
|
117
|
-
|
|
102
|
+
from whatap.llm.evaluators.hooks import enqueue
|
|
103
|
+
enqueue(pack)
|
|
118
104
|
except Exception as e:
|
|
119
105
|
logging.warning('[LLM] eval enqueue failed: %s' % e, extra={'id': 'LLM034'})
|
|
106
|
+
# <<< LLM-EVAL
|
|
120
107
|
|
|
121
108
|
def _enqueue_for_send(self, pack):
|
|
122
109
|
"""완성된 pack 을 송출 큐에 적재. queue full 이면 drop + LLM025."""
|
|
@@ -362,6 +349,7 @@ def send_llm_tx_status(ctx):
|
|
|
362
349
|
LlmLogSinkTask.get_instance().send_tx_status(ctx)
|
|
363
350
|
|
|
364
351
|
|
|
352
|
+
# >>> LLM-EVAL: 평가 결과 pack 송출구 — 평가 워커와 submit_evaluation 만 부른다.
|
|
365
353
|
def dispatch_llm_evaluation_pack(pack):
|
|
366
354
|
"""LlmStepEvalStatus pack 을 LogSink 인프라로 송출.
|
|
367
355
|
|
|
@@ -373,3 +361,4 @@ def dispatch_llm_evaluation_pack(pack):
|
|
|
373
361
|
except Exception as e:
|
|
374
362
|
logging.warning('[LLM] dispatch_llm_evaluation_pack failed: %s' % e,
|
|
375
363
|
extra={'id': 'LLM037'})
|
|
364
|
+
# <<< LLM-EVAL
|
|
@@ -229,7 +229,7 @@ def _llm_sdk_result(found):
|
|
|
229
229
|
|
|
230
230
|
|
|
231
231
|
def check_llm_features(conf, sdk_present):
|
|
232
|
-
"""LLM 관측 on/off
|
|
232
|
+
"""LLM 관측 on/off 상태를 요약한다."""
|
|
233
233
|
if conf is None or "__error__" in conf:
|
|
234
234
|
return None
|
|
235
235
|
llm_on = conf.get("llm_enabled", "false") == "true"
|
|
@@ -240,13 +240,18 @@ def check_llm_features(conf, sdk_present):
|
|
|
240
240
|
"(references/llm-observability.md)")
|
|
241
241
|
return Result(OK, "LLM 관측", "off")
|
|
242
242
|
|
|
243
|
+
result = Result(OK, "LLM 관측", "on")
|
|
244
|
+
# >>> LLM-EVAL: Evaluation 상태 요약(비용 경고 포함)
|
|
243
245
|
if conf.get("llm_eval_enabled", "false") == "true":
|
|
244
246
|
evs = conf.get("llm_eval_evaluators", "combined_judge, pii_leak, url_scan")
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
247
|
+
result = Result(WARN, "LLM Evaluation", "on / evaluators={0}".format(evs),
|
|
248
|
+
hint="judge LLM 호출만큼 토큰·비용이 추가 발생. combined_judge 권장, "
|
|
249
|
+
"필요시 llm_eval_sample_rate 로 비율 조절 (references/llm-evaluation.md)")
|
|
250
|
+
else:
|
|
251
|
+
result = Result(OK, "LLM 관측", "on (Evaluation off)",
|
|
252
|
+
hint="응답 품질 평가가 필요하면 llm_eval_enabled=true (references/llm-evaluation.md)")
|
|
253
|
+
# <<< LLM-EVAL
|
|
254
|
+
return result
|
|
250
255
|
|
|
251
256
|
|
|
252
257
|
def check_process():
|
|
@@ -279,7 +284,9 @@ _SCAN_PATTERNS = [
|
|
|
279
284
|
("workflow/agent", re.compile(r"@(workflow|agent|agent_name)\b|with\s+(workflow|agent|agent_name)\s*\(")),
|
|
280
285
|
("session/user", re.compile(r"set_(session|user)_id\s*\(|with\s+(session|user)\s*\(")),
|
|
281
286
|
("operation/prompt", re.compile(r"@prompt_meta\b|with\s+prompt_meta_scope\s*\(")),
|
|
287
|
+
# >>> LLM-EVAL: 고객 소스의 평가 API 사용
|
|
282
288
|
("evaluation", re.compile(r"@evaluate_with\b|evaluate_with\s*\(|with\s+evaluation_scope\s*\(")),
|
|
289
|
+
# <<< LLM-EVAL
|
|
283
290
|
("marker", re.compile(r"#\s*whatap")),
|
|
284
291
|
]
|
|
285
292
|
|
|
@@ -35,7 +35,6 @@ LangChain / LlamaIndex 등 AI 프레임워크 계측 시에도 framework 의 자
|
|
|
35
35
|
저장: trace context (있으면) + ContextVar (항상). 양쪽 동시에 같은 stack 을 push/pop.
|
|
36
36
|
중첩 안전 (LIFO stack). asyncio.create_task / TaskGroup 분기 시 ContextVar 가 inherit
|
|
37
37
|
되어 sub-task 안에서 LLM 호출 시에도 같은 prompt_meta 가 보임.
|
|
38
|
-
``whatap.llm.evaluators.scope`` 와 같은 패턴.
|
|
39
38
|
"""
|
|
40
39
|
import asyncio
|
|
41
40
|
import contextvars
|
|
@@ -52,11 +52,14 @@ EvaluatorContext = namedtuple(
|
|
|
52
52
|
# 인스턴스를 안 잡으므로 수명 무관. OAuth 등 못 읽으면 None → conf/env 로 폴백.
|
|
53
53
|
'judge_base_url', # str|None — 앱 client 의 base_url
|
|
54
54
|
'judge_api_key', # str|None — 앱 client 의 api_key
|
|
55
|
-
'judge_kind', # 'openai'|'anthropic'|None
|
|
55
|
+
'judge_kind', # 'openai'|'anthropic'|'bedrock'|None
|
|
56
|
+
# Bedrock 은 API 키가 아니라 AWS 자격증명으로 서명한다 — 앱 client 의 리전·엔드포인트와
|
|
57
|
+
# botocore 자격증명 객체(닫히지 않고, 갱신형은 judge 시점에 스스로 갱신)를 담는다.
|
|
58
|
+
'judge_aws', # dict|None — {'region', 'endpoint_url', 'profile', 'credentials'}
|
|
56
59
|
],
|
|
57
60
|
)
|
|
58
|
-
# 후행 optional 필드 defaults: event_loop, judge_base_url, judge_api_key, judge_kind
|
|
59
|
-
EvaluatorContext.__new__.__defaults__ = (None, None, None, None)
|
|
61
|
+
# 후행 optional 필드 defaults: event_loop, judge_base_url, judge_api_key, judge_kind, judge_aws
|
|
62
|
+
EvaluatorContext.__new__.__defaults__ = (None, None, None, None, None)
|
|
60
63
|
|
|
61
64
|
|
|
62
65
|
class EvaluatorResult(object):
|
|
@@ -47,7 +47,9 @@ LLM judge 기반 평가자는 별도 LLM 호출(judge call)로 점수를 산출
|
|
|
47
47
|
Judge LLM 호출 헬퍼:
|
|
48
48
|
|
|
49
49
|
make_openai_judge(client=..., model='gpt-4o-mini')
|
|
50
|
-
make_anthropic_judge(client=..., model='claude-
|
|
50
|
+
make_anthropic_judge(client=..., model='claude-haiku-5-5')
|
|
51
|
+
make_bedrock_judge(model='us.anthropic.claude-haiku-4-5-20251001-v1:0',
|
|
52
|
+
region_name='us-east-1') # Bedrock Runtime Converse (모델 필수)
|
|
51
53
|
|
|
52
54
|
커스텀 judge 작성 시 ``LLMJudgeBase`` 상속하고 ``make_prompt`` / ``parse_judgment`` 만
|
|
53
55
|
구현하면 된다.
|
|
@@ -56,6 +58,7 @@ from whatap.llm.evaluators.builtins.llm_judge import (
|
|
|
56
58
|
LLMJudgeBase,
|
|
57
59
|
make_openai_judge,
|
|
58
60
|
make_anthropic_judge,
|
|
61
|
+
make_bedrock_judge,
|
|
59
62
|
parse_json_response,
|
|
60
63
|
set_default_judge_fn,
|
|
61
64
|
get_default_judge_fn,
|
|
@@ -75,6 +78,7 @@ __all__ = [
|
|
|
75
78
|
'LLMJudgeBase',
|
|
76
79
|
'make_openai_judge',
|
|
77
80
|
'make_anthropic_judge',
|
|
81
|
+
'make_bedrock_judge',
|
|
78
82
|
'parse_json_response',
|
|
79
83
|
'set_default_judge_fn',
|
|
80
84
|
'get_default_judge_fn',
|