claude-smart 0.2.42 → 0.2.44
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.
- package/.claude-plugin/marketplace.json +3 -3
- package/README.md +1 -1
- package/bin/claude-smart.js +2 -2
- package/package.json +9 -3
- package/plugin/.claude-plugin/plugin.json +9 -3
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/README.md +23 -3
- package/plugin/pyproject.toml +3 -3
- package/plugin/scripts/_lib.sh +91 -0
- package/plugin/scripts/backend-service.sh +51 -4
- package/plugin/scripts/cli.sh +3 -1
- package/plugin/scripts/codex-hook.js +72 -4
- package/plugin/scripts/dashboard-build.sh +1 -0
- package/plugin/scripts/dashboard-service.sh +1 -0
- package/plugin/scripts/ensure-plugin-root.sh +1 -0
- package/plugin/scripts/hook_entry.sh +6 -3
- package/plugin/scripts/smart-install.sh +3 -2
- package/plugin/src/README.md +57 -0
- package/plugin/src/claude_smart/context_format.py +11 -12
- package/plugin/src/claude_smart/cs_cite.py +26 -12
- package/plugin/src/claude_smart/ids.py +13 -5
- package/plugin/uv.lock +126 -5
- package/plugin/vendor/reflexio/.env.example +62 -0
- package/plugin/vendor/reflexio/LICENSE +201 -0
- package/plugin/vendor/reflexio/README.md +338 -0
- package/plugin/vendor/reflexio/pyproject.toml +274 -0
- package/plugin/vendor/reflexio/reflexio/README.md +184 -0
- package/plugin/vendor/reflexio/reflexio/__init__.py +166 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/__init__.py +1 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/README.md +109 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/__init__.py +1 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/backends.py +175 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/bench.py +642 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/embed_cache.py +330 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/report.py +317 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/results/report.md +43 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/results/results.json +4478 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/scenarios.py +134 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/seed.py +255 -0
- package/plugin/vendor/reflexio/reflexio/cli/README.md +287 -0
- package/plugin/vendor/reflexio/reflexio/cli/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/cli/__main__.py +56 -0
- package/plugin/vendor/reflexio/reflexio/cli/_client.py +86 -0
- package/plugin/vendor/reflexio/reflexio/cli/app.py +127 -0
- package/plugin/vendor/reflexio/reflexio/cli/bootstrap_config.py +265 -0
- package/plugin/vendor/reflexio/reflexio/cli/codex_auth.py +503 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/admin_cmd.py +65 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/agent_playbooks.py +503 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/api.py +114 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/auth.py +109 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/config_cmd.py +511 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/doctor.py +127 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/embeddings.py +53 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/interactions.py +478 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/profiles.py +303 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/services.py +289 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/setup_cmd.py +964 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/shortcuts.py +285 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/status_cmd.py +143 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/user_playbooks.py +373 -0
- package/plugin/vendor/reflexio/reflexio/cli/env_loader.py +284 -0
- package/plugin/vendor/reflexio/reflexio/cli/errors.py +217 -0
- package/plugin/vendor/reflexio/reflexio/cli/log_format.py +247 -0
- package/plugin/vendor/reflexio/reflexio/cli/output.py +867 -0
- package/plugin/vendor/reflexio/reflexio/cli/paths.py +41 -0
- package/plugin/vendor/reflexio/reflexio/cli/run_services.py +391 -0
- package/plugin/vendor/reflexio/reflexio/cli/state.py +204 -0
- package/plugin/vendor/reflexio/reflexio/cli/stop_services.py +96 -0
- package/plugin/vendor/reflexio/reflexio/cli/utils.py +329 -0
- package/plugin/vendor/reflexio/reflexio/client/__init__.py +3 -0
- package/plugin/vendor/reflexio/reflexio/client/cache.py +150 -0
- package/plugin/vendor/reflexio/reflexio/client/client.py +2613 -0
- package/plugin/vendor/reflexio/reflexio/defaults.py +23 -0
- package/plugin/vendor/reflexio/reflexio/integrations/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/.clawhubignore +7 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/README.md +274 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/TESTING.md +517 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/hook/handler.js +473 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/package-lock.json +2156 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/package.json +18 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/hook/handler.ts +241 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/hook/setup.ts +140 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/index.ts +130 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/publish.ts +113 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/search.ts +52 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/server.ts +103 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/sqlite-buffer.ts +156 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/user-id.ts +134 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/openclaw.plugin.json +41 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/package.json +17 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/rules/reflexio.md +24 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/skills/reflexio/SKILL.md +48 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/publish_clawhub.sh +278 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/references/HOOK.md +164 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/scripts/install.sh +36 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/scripts/uninstall.sh +35 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/publish.test.ts +27 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/search.test.ts +31 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/server.test.ts +42 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/setup.test.ts +49 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/sqlite-buffer.test.ts +91 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/user-id.test.ts +50 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tsconfig.json +16 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/types/openclaw.d.ts +230 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/vitest.config.ts +13 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/README.md +120 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/TESTING.md +168 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/package-lock.json +1657 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/package.json +16 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/HEARTBEAT.md +6 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/README.md +84 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/SKILL.md +194 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/_meta.json +6 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/agents/reflexio-extractor.md +45 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/hook/handler.ts +214 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/hook/setup.ts +55 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/index.ts +327 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/consolidate.ts +233 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/dedup.ts +80 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/io.ts +155 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/openclaw-cli.ts +67 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/search.ts +33 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/write-playbook.ts +76 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/write-profile.ts +79 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/openclaw.plugin.json +46 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/package.json +18 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/prompts/README.md +36 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/prompts/full_consolidation.md +56 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/prompts/playbook_extraction.md +217 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/prompts/profile_extraction.md +132 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/skills/reflexio-consolidate/SKILL.md +33 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/skills/reflexio-embedded/SKILL.md +194 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/references/HOOK.md +18 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/references/architecture.md +49 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/references/comparison.md +31 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/references/future-work.md +47 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/references/porting-notes.md +52 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/scripts/install.sh +52 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/scripts/uninstall.sh +36 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/consolidate.test.ts +135 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/dedup.test.ts +104 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/io.test.ts +175 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/search.test.ts +66 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/smoke-test.ts +140 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/write-playbook.test.ts +93 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/write-profile.test.ts +174 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tsconfig.json +16 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/types/openclaw.d.ts +230 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/vitest.config.ts +7 -0
- package/plugin/vendor/reflexio/reflexio/lib/__init__.py +23 -0
- package/plugin/vendor/reflexio/reflexio/lib/_agent_playbook.py +310 -0
- package/plugin/vendor/reflexio/reflexio/lib/_base.py +225 -0
- package/plugin/vendor/reflexio/reflexio/lib/_config.py +83 -0
- package/plugin/vendor/reflexio/reflexio/lib/_dashboard.py +266 -0
- package/plugin/vendor/reflexio/reflexio/lib/_generation.py +176 -0
- package/plugin/vendor/reflexio/reflexio/lib/_interactions.py +334 -0
- package/plugin/vendor/reflexio/reflexio/lib/_operations.py +153 -0
- package/plugin/vendor/reflexio/reflexio/lib/_profiles.py +545 -0
- package/plugin/vendor/reflexio/reflexio/lib/_reflection.py +52 -0
- package/plugin/vendor/reflexio/reflexio/lib/_search.py +167 -0
- package/plugin/vendor/reflexio/reflexio/lib/_storage_labels.py +103 -0
- package/plugin/vendor/reflexio/reflexio/lib/_user_playbook.py +288 -0
- package/plugin/vendor/reflexio/reflexio/lib/reflexio_lib.py +27 -0
- package/plugin/vendor/reflexio/reflexio/models/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/braintrust_schema.py +141 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/common.py +41 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/__init__.py +3 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/entities.py +1112 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/enums.py +63 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/eval_overview_schema.py +487 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/internal_schema.py +28 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/pending_tool_call_schema.py +83 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/retriever_schema.py +768 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/service_schemas.py +9 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/stall_state_schema.py +32 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/ui/__init__.py +3 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/ui/converters.py +177 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/ui/entities.py +129 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/ui/enums.py +25 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/validators.py +333 -0
- package/plugin/vendor/reflexio/reflexio/models/config_schema.py +908 -0
- package/plugin/vendor/reflexio/reflexio/models/py.typed +0 -0
- package/plugin/vendor/reflexio/reflexio/server/OVERVIEW.md +90 -0
- package/plugin/vendor/reflexio/reflexio/server/README.md +622 -0
- package/plugin/vendor/reflexio/reflexio/server/__init__.py +210 -0
- package/plugin/vendor/reflexio/reflexio/server/__main__.py +132 -0
- package/plugin/vendor/reflexio/reflexio/server/_auth.py +25 -0
- package/plugin/vendor/reflexio/reflexio/server/api.py +2868 -0
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/README.md +34 -0
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/account_api.py +143 -0
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/health_api.py +91 -0
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/pending_tool_call_api.py +572 -0
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/precondition_checks.py +66 -0
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/publisher_api.py +562 -0
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/request_context.py +50 -0
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/stall_state_api.py +100 -0
- package/plugin/vendor/reflexio/reflexio/server/cache/__init__.py +15 -0
- package/plugin/vendor/reflexio/reflexio/server/cache/reflexio_cache.py +208 -0
- package/plugin/vendor/reflexio/reflexio/server/correlation.py +46 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/__init__.py +30 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/embedding_service.py +359 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/image_utils.py +55 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/litellm_client.py +1871 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/llm_utils.py +140 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/model_defaults.py +479 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/providers/__init__.py +1 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/providers/claude_code_provider.py +1122 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/providers/claude_code_stream_parser.py +197 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/providers/embedding_service_provider.py +338 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/providers/local_embedding_provider.py +213 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/providers/nomic_embedding_provider.py +288 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/rerank/__init__.py +6 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/rerank/cross_encoder_reranker.py +187 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/rerank/llm_reranker.py +148 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/tools.py +716 -0
- package/plugin/vendor/reflexio/reflexio/server/operation_limiter.py +179 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/_dispatchers.py +54 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/README.md +121 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/agent_success_evaluation/v1.0.0.prompt.md +58 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/agent_success_evaluation_with_comparison/v1.0.0.prompt.md +76 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/answer_synthesis/v1.5.2.prompt.md +88 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/compress_session_for_query/v1.3.0.prompt.md +31 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/document_expansion/v1.0.0.prompt.md +20 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.0.0.prompt.md +53 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.1.0.prompt.md +57 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.2.0.prompt.md +68 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.3.0.prompt.md +70 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.4.0.prompt.md +77 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.5.0.prompt.md +82 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.6.0.prompt.md +83 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_aggregation/v2.1.0.prompt.md +193 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_aggregation/v2.2.0.prompt.md +206 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v1.0.0-deprecated.prompt.md +66 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v1.0.0.prompt.md +43 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v1.1.0.prompt.md +46 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.0.0-deprecated.prompt.md +64 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.0.0.prompt.md +39 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.1.0.prompt.md +39 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.2.0.prompt.md +47 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.3.0.prompt.md +58 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.3.1.prompt.md +69 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.3.2.prompt.md +71 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.0.2.prompt.md +254 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.1.0.prompt.md +274 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.2.0.prompt.md +283 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.2.2.prompt.md +234 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.2.3.prompt.md +244 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v1.0.0.prompt.md +73 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v2.0.0.prompt.md +86 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v3.0.0.prompt.md +97 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v3.1.0.prompt.md +119 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v3.2.0.prompt.md +123 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v3.3.0.prompt.md +137 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main/v1.0.0.prompt.md +14 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main/v1.1.0.prompt.md +24 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main/v1.2.0.prompt.md +29 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main_expert/v1.0.0.prompt.md +11 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main_expert/v1.1.0.prompt.md +21 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main_expert/v1.2.0.prompt.md +25 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_optimizer_judge/v1.0.0.prompt.md +37 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_optimizer_judge/v1.1.0.prompt.md +40 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_optimizer_judge/v1.2.0.prompt.md +36 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_should_generate/v1.0.0.prompt.md +45 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_should_generate/v2.0.0.prompt.md +81 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_should_generate/v3.0.0.prompt.md +80 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_should_generate_expert/v1.0.0.prompt.md +34 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_deduplication/v1.0.0.prompt.md +116 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_should_generate/v1.0.0.prompt.md +33 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_should_generate_override/v1.0.0.prompt.md +16 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_update_instruction_start/v1.0.0.prompt.md +140 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_update_instruction_start/v1.1.0.prompt.md +160 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_update_main/v1.0.0.prompt.md +14 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/query_reformulation/v1.0.0.prompt.md +19 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/rerank_relevance/v1.1.0.prompt.md +44 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/shadow_comparison/v1.0.0.prompt.md +43 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/shadow_content_evaluation/v1.0.0.prompt.md +33 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_evaluation/prompt_evaluation_dataset/feedback_extraction_main_v1.jsonl +10 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_evaluation/prompt_evaluation_dataset/profile_update_main_v1.jsonl +10 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_manager.py +280 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_schema.py +11 -0
- package/plugin/vendor/reflexio/reflexio/server/services/README.md +58 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/_eval_health.py +131 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/agent_success_evaluation_constants.py +60 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/agent_success_evaluation_service.py +228 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/agent_success_evaluation_utils.py +87 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/agent_success_evaluator.py +372 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/delayed_group_evaluator.py +156 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/group_evaluation_runner.py +336 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/regen_jobs.py +471 -0
- package/plugin/vendor/reflexio/reflexio/server/services/base_generation_service.py +1668 -0
- package/plugin/vendor/reflexio/reflexio/server/services/braintrust/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/server/services/braintrust/_cron.py +196 -0
- package/plugin/vendor/reflexio/reflexio/server/services/braintrust/_encryption.py +101 -0
- package/plugin/vendor/reflexio/reflexio/server/services/braintrust/client.py +167 -0
- package/plugin/vendor/reflexio/reflexio/server/services/braintrust/service.py +281 -0
- package/plugin/vendor/reflexio/reflexio/server/services/configurator/base_configurator.py +179 -0
- package/plugin/vendor/reflexio/reflexio/server/services/configurator/config_storage.py +62 -0
- package/plugin/vendor/reflexio/reflexio/server/services/configurator/configurator.py +87 -0
- package/plugin/vendor/reflexio/reflexio/server/services/configurator/local_file_config_storage.py +187 -0
- package/plugin/vendor/reflexio/reflexio/server/services/configurator/test_config_storage.py +162 -0
- package/plugin/vendor/reflexio/reflexio/server/services/deduplication_utils.py +112 -0
- package/plugin/vendor/reflexio/reflexio/server/services/embedding_text.py +62 -0
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/distribution.py +33 -0
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/eval_sampler.py +126 -0
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/group_aggregation.py +192 -0
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/hero_state.py +75 -0
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/rule_attribution.py +97 -0
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/service.py +515 -0
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/shadow_aggregation.py +90 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/agent_run_records.py +91 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/invariants.py +303 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/outcome.py +25 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/pending_tool_call_dispatch.py +358 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/plan.py +138 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/prior_answer_search.py +217 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/resumable_agent.py +535 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/resume_scheduler.py +171 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/resume_worker.py +779 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/tools.py +1125 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extractor_config_utils.py +94 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extractor_interaction_utils.py +251 -0
- package/plugin/vendor/reflexio/reflexio/server/services/generation_service.py +702 -0
- package/plugin/vendor/reflexio/reflexio/server/services/operation_state_utils.py +835 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/README.md +89 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_aggregator.py +1388 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_consolidator.py +1045 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_extractor.py +436 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_generation_service.py +808 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_service_constants.py +28 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_service_utils.py +362 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/__init__.py +24 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/assistant_webhook.py +246 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/gepa_adapter.py +291 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/judge.py +97 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/models.py +96 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/optimizer.py +645 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/rollout.py +35 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/scenario_resolver.py +93 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/scheduler.py +174 -0
- package/plugin/vendor/reflexio/reflexio/server/services/pre_retrieval/__init__.py +26 -0
- package/plugin/vendor/reflexio/reflexio/server/services/pre_retrieval/_document_expander.py +179 -0
- package/plugin/vendor/reflexio/reflexio/server/services/pre_retrieval/_query_reformulator.py +297 -0
- package/plugin/vendor/reflexio/reflexio/server/services/profile/profile_deduplicator.py +772 -0
- package/plugin/vendor/reflexio/reflexio/server/services/profile/profile_extractor.py +462 -0
- package/plugin/vendor/reflexio/reflexio/server/services/profile/profile_generation_service.py +737 -0
- package/plugin/vendor/reflexio/reflexio/server/services/profile/profile_generation_service_utils.py +290 -0
- package/plugin/vendor/reflexio/reflexio/server/services/reflection/__init__.py +17 -0
- package/plugin/vendor/reflexio/reflexio/server/services/reflection/reflection_extractor.py +247 -0
- package/plugin/vendor/reflexio/reflexio/server/services/reflection/reflection_service.py +803 -0
- package/plugin/vendor/reflexio/reflexio/server/services/reflection/reflection_service_utils.py +146 -0
- package/plugin/vendor/reflexio/reflexio/server/services/retrieval/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/server/services/retrieval/relevance_floor.py +80 -0
- package/plugin/vendor/reflexio/reflexio/server/services/search/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/server/services/service_utils.py +756 -0
- package/plugin/vendor/reflexio/reflexio/server/services/shadow_comparison/__init__.py +1 -0
- package/plugin/vendor/reflexio/reflexio/server/services/shadow_comparison/judge.py +184 -0
- package/plugin/vendor/reflexio/reflexio/server/services/shadow_comparison/outcome.py +81 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/constants.py +2 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/error.py +11 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/retention.py +154 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/retention_mixin.py +155 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/__init__.py +59 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_agent_run.py +1298 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_base.py +1945 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_extras.py +600 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_operations.py +346 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_playbook.py +1378 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_profiles.py +747 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_requests.py +263 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_shadow_verdicts.py +193 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_share_links.py +166 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_stall_state.py +217 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/__init__.py +153 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_agent_run.py +384 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_base.py +71 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_extras.py +235 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_operations.py +170 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_playbook.py +677 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_profiles.py +250 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_requests.py +154 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_shadow_verdicts.py +130 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_share_links.py +93 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_stall_state.py +76 -0
- package/plugin/vendor/reflexio/reflexio/server/services/unified_search_service.py +572 -0
- package/plugin/vendor/reflexio/reflexio/server/site_var/README.md +77 -0
- package/plugin/vendor/reflexio/reflexio/server/site_var/feature_flags.py +116 -0
- package/plugin/vendor/reflexio/reflexio/server/site_var/site_var_manager.py +263 -0
- package/plugin/vendor/reflexio/reflexio/server/site_var/site_var_sources/feature_flags.json +13 -0
- package/plugin/vendor/reflexio/reflexio/server/site_var/site_var_sources/llm_model_setting.json +7 -0
- package/plugin/vendor/reflexio/reflexio/server/tracing.py +158 -0
- package/plugin/vendor/reflexio/reflexio/server/usage_metrics.py +113 -0
- package/plugin/vendor/reflexio/reflexio/server/uvicorn_logging.py +76 -0
- package/plugin/vendor/reflexio/reflexio/test_support/__init__.py +1 -0
- package/plugin/vendor/reflexio/reflexio/test_support/llm_fixtures.py +62 -0
- package/plugin/vendor/reflexio/reflexio/test_support/llm_mock.py +242 -0
- package/plugin/vendor/reflexio/reflexio/test_support/llm_model_registry.py +129 -0
- package/plugin/vendor/reflexio/reflexio/test_support/skip_decorators.py +43 -0
|
@@ -0,0 +1,642 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Retrieval latency benchmark — main CLI entry point.
|
|
3
|
+
|
|
4
|
+
Measures end-to-end latency for profile search, user/agent playbook search,
|
|
5
|
+
and unified cross-entity search across storage backends and corpus sizes.
|
|
6
|
+
Two layers are supported:
|
|
7
|
+
|
|
8
|
+
- ``service`` — direct method call on :class:`Reflexio` (in-process, no
|
|
9
|
+
HTTP). Measures reformulation + embedding lookup + storage retrieval.
|
|
10
|
+
- ``http`` — FastAPI ``TestClient`` POST to the corresponding ``/api/...``
|
|
11
|
+
endpoint. Measures the same thing plus FastAPI routing, Pydantic
|
|
12
|
+
serialization, and middleware overhead. No sockets — TCP/kernel cost is
|
|
13
|
+
not included.
|
|
14
|
+
|
|
15
|
+
Query embeddings are pre-cached on disk (see :mod:`embed_cache`), so
|
|
16
|
+
embedder latency does not contaminate the measurement. Document embeddings
|
|
17
|
+
during seeding are deterministic fakes — document vector content doesn't
|
|
18
|
+
affect query-time latency, only row count does.
|
|
19
|
+
|
|
20
|
+
Usage::
|
|
21
|
+
|
|
22
|
+
uv run python -m reflexio.benchmarks.retrieval_latency.bench \\
|
|
23
|
+
--sizes 100,1000 --trials 30 --backend sqlite --layer service,http
|
|
24
|
+
|
|
25
|
+
See ``--help`` for the full flag list.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
from __future__ import annotations
|
|
29
|
+
|
|
30
|
+
import argparse
|
|
31
|
+
import json
|
|
32
|
+
import logging
|
|
33
|
+
import subprocess
|
|
34
|
+
import sys
|
|
35
|
+
import time
|
|
36
|
+
from collections.abc import Callable
|
|
37
|
+
from contextlib import ExitStack
|
|
38
|
+
from datetime import UTC, datetime
|
|
39
|
+
from pathlib import Path
|
|
40
|
+
from typing import Any, Literal, cast
|
|
41
|
+
|
|
42
|
+
from reflexio.benchmarks.retrieval_latency.backends import (
|
|
43
|
+
BACKENDS,
|
|
44
|
+
BENCH_ORG_ID,
|
|
45
|
+
BackendHandle,
|
|
46
|
+
)
|
|
47
|
+
from reflexio.benchmarks.retrieval_latency.embed_cache import (
|
|
48
|
+
QueryEmbedCache,
|
|
49
|
+
make_cached_query_embedder,
|
|
50
|
+
patch_storage_get_embedding,
|
|
51
|
+
)
|
|
52
|
+
from reflexio.benchmarks.retrieval_latency.report import (
|
|
53
|
+
RunResults,
|
|
54
|
+
aggregate,
|
|
55
|
+
load_baseline,
|
|
56
|
+
render_markdown,
|
|
57
|
+
write_results_json,
|
|
58
|
+
)
|
|
59
|
+
from reflexio.benchmarks.retrieval_latency.scenarios import QUERIES
|
|
60
|
+
from reflexio.benchmarks.retrieval_latency.seed import pick_bench_user_id, seed_corpus
|
|
61
|
+
from reflexio.lib.reflexio_lib import Reflexio
|
|
62
|
+
from reflexio.models.api_schema.retriever_schema import (
|
|
63
|
+
SearchAgentPlaybookRequest,
|
|
64
|
+
SearchUserPlaybookRequest,
|
|
65
|
+
SearchUserProfileRequest,
|
|
66
|
+
UnifiedSearchRequest,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
logger = logging.getLogger("reflexio.benchmarks.retrieval_latency")
|
|
70
|
+
|
|
71
|
+
Layer = Literal["service", "http"]
|
|
72
|
+
RetrievalType = Literal["profile", "user_playbook", "agent_playbook", "unified"]
|
|
73
|
+
|
|
74
|
+
DEFAULT_SIZES = (100, 1_000, 10_000)
|
|
75
|
+
DEFAULT_TRIALS = 50
|
|
76
|
+
DEFAULT_WARMUP = 5
|
|
77
|
+
DEFAULT_BACKENDS = ("sqlite", "supabase")
|
|
78
|
+
DEFAULT_LAYERS = ("service", "http")
|
|
79
|
+
DEFAULT_RETRIEVALS = ("profile", "user_playbook", "agent_playbook", "unified")
|
|
80
|
+
|
|
81
|
+
# Default output lives next to the bench module so reports are colocated with
|
|
82
|
+
# the script that produced them, not stranded at the repo root.
|
|
83
|
+
_THIS_DIR = Path(__file__).resolve().parent
|
|
84
|
+
_DEFAULT_OUTPUT_ROOT = _THIS_DIR / "results"
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def _build_profile_request(query_idx: int) -> SearchUserProfileRequest:
|
|
88
|
+
"""
|
|
89
|
+
Build a profile search request bound to the canned query set.
|
|
90
|
+
|
|
91
|
+
Reformulation is disabled so the benchmark does not measure LLM cost.
|
|
92
|
+
|
|
93
|
+
Args:
|
|
94
|
+
query_idx (int): Index into the canned query set (wraps around).
|
|
95
|
+
|
|
96
|
+
Returns:
|
|
97
|
+
SearchUserProfileRequest: A ready-to-execute request.
|
|
98
|
+
"""
|
|
99
|
+
return SearchUserProfileRequest(
|
|
100
|
+
user_id=pick_bench_user_id(query_idx),
|
|
101
|
+
query=QUERIES[query_idx % len(QUERIES)],
|
|
102
|
+
top_k=10,
|
|
103
|
+
enable_reformulation=False,
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def _build_user_playbook_request(query_idx: int) -> SearchUserPlaybookRequest:
|
|
108
|
+
"""
|
|
109
|
+
Build a user playbook search request.
|
|
110
|
+
|
|
111
|
+
Args:
|
|
112
|
+
query_idx (int): Index into the canned query set (wraps around).
|
|
113
|
+
|
|
114
|
+
Returns:
|
|
115
|
+
SearchUserPlaybookRequest: A ready-to-execute request.
|
|
116
|
+
"""
|
|
117
|
+
return SearchUserPlaybookRequest(
|
|
118
|
+
query=QUERIES[query_idx % len(QUERIES)],
|
|
119
|
+
user_id=pick_bench_user_id(query_idx),
|
|
120
|
+
top_k=10,
|
|
121
|
+
enable_reformulation=False,
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def _build_agent_playbook_request(query_idx: int) -> SearchAgentPlaybookRequest:
|
|
126
|
+
"""
|
|
127
|
+
Build an agent playbook search request.
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
query_idx (int): Index into the canned query set (wraps around).
|
|
131
|
+
|
|
132
|
+
Returns:
|
|
133
|
+
SearchAgentPlaybookRequest: A ready-to-execute request.
|
|
134
|
+
"""
|
|
135
|
+
return SearchAgentPlaybookRequest(
|
|
136
|
+
query=QUERIES[query_idx % len(QUERIES)],
|
|
137
|
+
top_k=10,
|
|
138
|
+
enable_reformulation=False,
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def _build_unified_request(query_idx: int) -> UnifiedSearchRequest:
|
|
143
|
+
"""
|
|
144
|
+
Build a unified search request.
|
|
145
|
+
|
|
146
|
+
Args:
|
|
147
|
+
query_idx (int): Index into the canned query set (wraps around).
|
|
148
|
+
|
|
149
|
+
Returns:
|
|
150
|
+
UnifiedSearchRequest: A ready-to-execute request.
|
|
151
|
+
"""
|
|
152
|
+
return UnifiedSearchRequest(
|
|
153
|
+
query=QUERIES[query_idx % len(QUERIES)],
|
|
154
|
+
user_id=pick_bench_user_id(query_idx),
|
|
155
|
+
top_k=10,
|
|
156
|
+
enable_reformulation=False,
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def _service_call(
|
|
161
|
+
reflexio: Reflexio,
|
|
162
|
+
retrieval: RetrievalType,
|
|
163
|
+
query_idx: int,
|
|
164
|
+
org_id: str,
|
|
165
|
+
) -> None:
|
|
166
|
+
"""
|
|
167
|
+
Execute one service-layer retrieval call in-process.
|
|
168
|
+
|
|
169
|
+
Dispatches on ``retrieval`` to the matching ``Reflexio`` facade method.
|
|
170
|
+
The response is discarded — the benchmark measures time, not accuracy.
|
|
171
|
+
|
|
172
|
+
Args:
|
|
173
|
+
reflexio (Reflexio): Live service-layer facade.
|
|
174
|
+
retrieval (RetrievalType): Which retrieval path to exercise.
|
|
175
|
+
query_idx (int): Query index to use for this call.
|
|
176
|
+
org_id (str): Org ID for unified search's feature-flag checks.
|
|
177
|
+
"""
|
|
178
|
+
match retrieval:
|
|
179
|
+
case "profile":
|
|
180
|
+
reflexio.search_user_profiles(_build_profile_request(query_idx))
|
|
181
|
+
case "user_playbook":
|
|
182
|
+
reflexio.search_user_playbooks(_build_user_playbook_request(query_idx))
|
|
183
|
+
case "agent_playbook":
|
|
184
|
+
reflexio.search_agent_playbooks(_build_agent_playbook_request(query_idx))
|
|
185
|
+
case "unified":
|
|
186
|
+
reflexio.unified_search(_build_unified_request(query_idx), org_id=org_id)
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
# Map retrieval type to (HTTP path, request builder) for the http layer.
|
|
190
|
+
_HTTP_ROUTES: dict[RetrievalType, tuple[str, Callable[[int], Any]]] = {
|
|
191
|
+
"profile": ("/api/search_profiles", _build_profile_request),
|
|
192
|
+
"user_playbook": ("/api/search_user_playbooks", _build_user_playbook_request),
|
|
193
|
+
"agent_playbook": ("/api/search_agent_playbooks", _build_agent_playbook_request),
|
|
194
|
+
"unified": ("/api/search", _build_unified_request),
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def _http_call(client: Any, retrieval: RetrievalType, query_idx: int) -> None:
|
|
199
|
+
"""
|
|
200
|
+
Execute one HTTP-layer retrieval call via FastAPI ``TestClient``.
|
|
201
|
+
|
|
202
|
+
Args:
|
|
203
|
+
client: A fastapi.testclient.TestClient bound to the benchmark app.
|
|
204
|
+
retrieval (RetrievalType): Which retrieval path to exercise.
|
|
205
|
+
query_idx (int): Query index to use for this call.
|
|
206
|
+
|
|
207
|
+
Raises:
|
|
208
|
+
RuntimeError: If the endpoint returns a non-200 response — that
|
|
209
|
+
indicates a wiring problem, not a latency result, and should
|
|
210
|
+
abort the run.
|
|
211
|
+
"""
|
|
212
|
+
path, build = _HTTP_ROUTES[retrieval]
|
|
213
|
+
payload = build(query_idx).model_dump(mode="json")
|
|
214
|
+
resp = client.post(path, json=payload)
|
|
215
|
+
if resp.status_code != 200:
|
|
216
|
+
raise RuntimeError(
|
|
217
|
+
f"HTTP benchmark call failed: {retrieval} {path} -> "
|
|
218
|
+
f"{resp.status_code} {resp.text[:200]}"
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def _make_test_client(handle: BackendHandle) -> Any:
|
|
223
|
+
"""
|
|
224
|
+
Build a FastAPI ``TestClient`` wired to the benchmark Reflexio instance.
|
|
225
|
+
|
|
226
|
+
The server-side ``get_reflexio`` cache is pre-populated so FastAPI
|
|
227
|
+
handlers reuse our pre-seeded instance instead of creating their own
|
|
228
|
+
(which would have no data and no custom storage config).
|
|
229
|
+
|
|
230
|
+
Args:
|
|
231
|
+
handle (BackendHandle): The live benchmark backend handle.
|
|
232
|
+
|
|
233
|
+
Returns:
|
|
234
|
+
TestClient: A fastapi.testclient.TestClient bound to a fresh app.
|
|
235
|
+
"""
|
|
236
|
+
from fastapi.testclient import TestClient
|
|
237
|
+
|
|
238
|
+
from reflexio.server.api import create_app
|
|
239
|
+
from reflexio.server.cache import reflexio_cache
|
|
240
|
+
|
|
241
|
+
with reflexio_cache._reflexio_cache_lock:
|
|
242
|
+
reflexio_cache._reflexio_cache[(handle.org_id, None)] = handle.reflexio
|
|
243
|
+
|
|
244
|
+
app = create_app(get_org_id=lambda: handle.org_id)
|
|
245
|
+
return TestClient(app)
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
def _time_loop(
|
|
249
|
+
call: Callable[[int], None],
|
|
250
|
+
trials: int,
|
|
251
|
+
warmup: int,
|
|
252
|
+
) -> list[float]:
|
|
253
|
+
"""
|
|
254
|
+
Run ``warmup`` + ``trials`` timed invocations and return sample ms.
|
|
255
|
+
|
|
256
|
+
Warmup invocations are discarded. Each sample uses
|
|
257
|
+
:func:`time.perf_counter_ns` so the clock is monotonic and has
|
|
258
|
+
sub-microsecond resolution on all supported platforms.
|
|
259
|
+
|
|
260
|
+
Args:
|
|
261
|
+
call (Callable[[int], None]): Fn that takes a query index and runs
|
|
262
|
+
one benchmark invocation.
|
|
263
|
+
trials (int): Number of timed samples to collect.
|
|
264
|
+
warmup (int): Number of untimed warmup invocations.
|
|
265
|
+
|
|
266
|
+
Returns:
|
|
267
|
+
list[float]: ``trials`` latency samples in milliseconds.
|
|
268
|
+
"""
|
|
269
|
+
for i in range(warmup):
|
|
270
|
+
call(i)
|
|
271
|
+
samples: list[float] = []
|
|
272
|
+
for i in range(trials):
|
|
273
|
+
t0 = time.perf_counter_ns()
|
|
274
|
+
call(i)
|
|
275
|
+
samples.append((time.perf_counter_ns() - t0) / 1_000_000.0)
|
|
276
|
+
return samples
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
def _git_sha() -> str:
|
|
280
|
+
"""
|
|
281
|
+
Return the current git HEAD short SHA, or ``"unknown"`` if unavailable.
|
|
282
|
+
|
|
283
|
+
Used for run provenance in the results JSON. Never raises — the
|
|
284
|
+
benchmark must complete even when the checkout isn't a git repo.
|
|
285
|
+
|
|
286
|
+
Returns:
|
|
287
|
+
str: Short SHA or ``"unknown"``.
|
|
288
|
+
"""
|
|
289
|
+
try:
|
|
290
|
+
out = subprocess.run(
|
|
291
|
+
["git", "rev-parse", "--short", "HEAD"], # noqa: S607
|
|
292
|
+
check=True,
|
|
293
|
+
capture_output=True,
|
|
294
|
+
text=True,
|
|
295
|
+
timeout=5,
|
|
296
|
+
)
|
|
297
|
+
return out.stdout.strip() or "unknown"
|
|
298
|
+
except (subprocess.SubprocessError, FileNotFoundError, OSError):
|
|
299
|
+
return "unknown"
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
def _run_one_cell(
|
|
303
|
+
handle: BackendHandle,
|
|
304
|
+
client: Any | None,
|
|
305
|
+
retrieval: RetrievalType,
|
|
306
|
+
layer: Layer,
|
|
307
|
+
n: int,
|
|
308
|
+
trials: int,
|
|
309
|
+
warmup: int,
|
|
310
|
+
) -> list[dict[str, Any]]:
|
|
311
|
+
"""
|
|
312
|
+
Benchmark one ``(backend, retrieval, layer, n)`` cell and return rows.
|
|
313
|
+
|
|
314
|
+
Args:
|
|
315
|
+
handle (BackendHandle): Live backend handle.
|
|
316
|
+
client: FastAPI TestClient (only required for ``layer='http'``).
|
|
317
|
+
retrieval (RetrievalType): Which retrieval path to exercise.
|
|
318
|
+
layer (Layer): ``service`` or ``http``.
|
|
319
|
+
n (int): Corpus size already seeded into the backend.
|
|
320
|
+
trials (int): Timed samples per cell.
|
|
321
|
+
warmup (int): Untimed warmup invocations per cell.
|
|
322
|
+
|
|
323
|
+
Returns:
|
|
324
|
+
list[dict]: One row per trial, ready to append to raw results.
|
|
325
|
+
"""
|
|
326
|
+
if layer == "service":
|
|
327
|
+
|
|
328
|
+
def call(qi: int) -> None:
|
|
329
|
+
_service_call(handle.reflexio, retrieval, qi, handle.org_id)
|
|
330
|
+
else:
|
|
331
|
+
if client is None:
|
|
332
|
+
raise RuntimeError("http layer requires a TestClient")
|
|
333
|
+
|
|
334
|
+
def call(qi: int) -> None:
|
|
335
|
+
_http_call(client, retrieval, qi)
|
|
336
|
+
|
|
337
|
+
samples = _time_loop(call, trials=trials, warmup=warmup)
|
|
338
|
+
return [
|
|
339
|
+
{
|
|
340
|
+
"backend": handle.name,
|
|
341
|
+
"retrieval_type": retrieval,
|
|
342
|
+
"layer": layer,
|
|
343
|
+
"n": n,
|
|
344
|
+
"trial": i,
|
|
345
|
+
"elapsed_ms": sample,
|
|
346
|
+
"query_idx": i % len(QUERIES),
|
|
347
|
+
}
|
|
348
|
+
for i, sample in enumerate(samples)
|
|
349
|
+
]
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
def _run_for_backend(
|
|
353
|
+
handle: BackendHandle,
|
|
354
|
+
sizes: list[int],
|
|
355
|
+
layers: list[Layer],
|
|
356
|
+
retrievals: list[RetrievalType],
|
|
357
|
+
trials: int,
|
|
358
|
+
warmup: int,
|
|
359
|
+
embed_cache: QueryEmbedCache,
|
|
360
|
+
) -> list[dict[str, Any]]:
|
|
361
|
+
"""
|
|
362
|
+
Run the full (N × retrieval × layer) sweep on one backend.
|
|
363
|
+
|
|
364
|
+
For each N: wipes the backend, re-seeds ``n`` rows of each entity type,
|
|
365
|
+
then patches the storage with the cached query embedder and executes
|
|
366
|
+
every (retrieval × layer) cell.
|
|
367
|
+
|
|
368
|
+
A single wipe failure is tolerated (and logged) so a flaky delete doesn't
|
|
369
|
+
abort a full run, but two consecutive failures raise — repeated failures
|
|
370
|
+
silently contaminate larger-N cells with stale rows from smaller-N runs,
|
|
371
|
+
which looks like a perf change in the report for no real reason.
|
|
372
|
+
|
|
373
|
+
Args:
|
|
374
|
+
handle (BackendHandle): Live backend handle.
|
|
375
|
+
sizes (list[int]): Corpus sizes to sweep.
|
|
376
|
+
layers (list[Layer]): Layers to benchmark.
|
|
377
|
+
retrievals (list[RetrievalType]): Retrieval types to benchmark.
|
|
378
|
+
trials (int): Timed samples per cell.
|
|
379
|
+
warmup (int): Untimed warmup invocations per cell.
|
|
380
|
+
embed_cache (QueryEmbedCache): Pre-populated query embedding cache.
|
|
381
|
+
|
|
382
|
+
Returns:
|
|
383
|
+
list[dict]: All raw rows for this backend.
|
|
384
|
+
|
|
385
|
+
Raises:
|
|
386
|
+
RuntimeError: If ``_wipe_backend`` fails twice in a row on the same
|
|
387
|
+
backend, indicating delete is broken and every subsequent cell
|
|
388
|
+
would be reading contaminated data.
|
|
389
|
+
"""
|
|
390
|
+
rows: list[dict[str, Any]] = []
|
|
391
|
+
client: Any | None = None
|
|
392
|
+
if "http" in layers:
|
|
393
|
+
client = _make_test_client(handle)
|
|
394
|
+
consecutive_wipe_failures = 0
|
|
395
|
+
for n in sizes:
|
|
396
|
+
logger.info("Backend=%s, seeding N=%d", handle.name, n)
|
|
397
|
+
if _wipe_backend(handle):
|
|
398
|
+
consecutive_wipe_failures = 0
|
|
399
|
+
else:
|
|
400
|
+
consecutive_wipe_failures += 1
|
|
401
|
+
if consecutive_wipe_failures >= 2:
|
|
402
|
+
raise RuntimeError(
|
|
403
|
+
f"Backend {handle.name!r} wipe failed twice in a row; "
|
|
404
|
+
"aborting so larger-N cells don't get contaminated with "
|
|
405
|
+
"rows from previous runs."
|
|
406
|
+
)
|
|
407
|
+
seed_corpus(handle.reflexio, handle.storage, n)
|
|
408
|
+
cached = make_cached_query_embedder(embed_cache)
|
|
409
|
+
with patch_storage_get_embedding(handle.storage, cached):
|
|
410
|
+
for retrieval in retrievals:
|
|
411
|
+
for layer in layers:
|
|
412
|
+
logger.info(
|
|
413
|
+
"Measuring backend=%s retrieval=%s layer=%s N=%d",
|
|
414
|
+
handle.name,
|
|
415
|
+
retrieval,
|
|
416
|
+
layer,
|
|
417
|
+
n,
|
|
418
|
+
)
|
|
419
|
+
rows.extend(
|
|
420
|
+
_run_one_cell(
|
|
421
|
+
handle=handle,
|
|
422
|
+
client=client,
|
|
423
|
+
retrieval=retrieval,
|
|
424
|
+
layer=layer,
|
|
425
|
+
n=n,
|
|
426
|
+
trials=trials,
|
|
427
|
+
warmup=warmup,
|
|
428
|
+
)
|
|
429
|
+
)
|
|
430
|
+
return rows
|
|
431
|
+
|
|
432
|
+
|
|
433
|
+
def _wipe_backend(handle: BackendHandle) -> bool:
|
|
434
|
+
"""
|
|
435
|
+
Delete all seeded data from a backend so the next ``N`` starts fresh.
|
|
436
|
+
|
|
437
|
+
Logs and swallows a single failure — the caller tracks consecutive
|
|
438
|
+
failures and aborts on the second one, so one flaky delete doesn't kill
|
|
439
|
+
a whole run but a broken delete path does.
|
|
440
|
+
|
|
441
|
+
Args:
|
|
442
|
+
handle (BackendHandle): Live backend handle.
|
|
443
|
+
|
|
444
|
+
Returns:
|
|
445
|
+
bool: ``True`` if every delete-all call succeeded, ``False`` if any
|
|
446
|
+
raised. ``False`` signals the caller to bump its consecutive
|
|
447
|
+
failure counter.
|
|
448
|
+
"""
|
|
449
|
+
try:
|
|
450
|
+
handle.reflexio.delete_all_profiles_bulk()
|
|
451
|
+
handle.reflexio.delete_all_user_playbooks_bulk()
|
|
452
|
+
handle.reflexio.delete_all_agent_playbooks_bulk()
|
|
453
|
+
except Exception as err: # noqa: BLE001
|
|
454
|
+
logger.warning("Backend wipe failed on %s: %s", handle.name, err)
|
|
455
|
+
return False
|
|
456
|
+
return True
|
|
457
|
+
|
|
458
|
+
|
|
459
|
+
def _parse_csv_list[T](raw: str, valid: tuple[T, ...]) -> list[T]:
|
|
460
|
+
"""
|
|
461
|
+
Parse a comma-separated CLI value against an allowlist.
|
|
462
|
+
|
|
463
|
+
Args:
|
|
464
|
+
raw (str): Raw CLI value, e.g. ``"sqlite,supabase"``.
|
|
465
|
+
valid (tuple[T, ...]): Allowed values.
|
|
466
|
+
|
|
467
|
+
Returns:
|
|
468
|
+
list[T]: Parsed values in input order.
|
|
469
|
+
|
|
470
|
+
Raises:
|
|
471
|
+
ValueError: If any entry is not in ``valid``.
|
|
472
|
+
"""
|
|
473
|
+
items = [x.strip() for x in raw.split(",") if x.strip()]
|
|
474
|
+
for item in items:
|
|
475
|
+
if item not in valid:
|
|
476
|
+
raise ValueError(f"Invalid value {item!r}; choose from {valid}")
|
|
477
|
+
return items # type: ignore[return-value]
|
|
478
|
+
|
|
479
|
+
|
|
480
|
+
def _parse_sizes(raw: str) -> list[int]:
|
|
481
|
+
"""
|
|
482
|
+
Parse a comma-separated list of corpus sizes from the CLI.
|
|
483
|
+
|
|
484
|
+
Args:
|
|
485
|
+
raw (str): E.g. ``"100,1000,10000"``.
|
|
486
|
+
|
|
487
|
+
Returns:
|
|
488
|
+
list[int]: Parsed integers, sorted ascending.
|
|
489
|
+
|
|
490
|
+
Raises:
|
|
491
|
+
ValueError: If any token is not a positive integer.
|
|
492
|
+
"""
|
|
493
|
+
sizes = [int(x.strip()) for x in raw.split(",") if x.strip()]
|
|
494
|
+
if any(s <= 0 for s in sizes):
|
|
495
|
+
raise ValueError("Sizes must be positive integers")
|
|
496
|
+
return sorted(sizes)
|
|
497
|
+
|
|
498
|
+
|
|
499
|
+
def _parse_args(argv: list[str] | None = None) -> argparse.Namespace:
|
|
500
|
+
"""
|
|
501
|
+
Parse CLI arguments for the benchmark.
|
|
502
|
+
|
|
503
|
+
Args:
|
|
504
|
+
argv (list[str] | None): Argument list, or ``None`` for sys.argv.
|
|
505
|
+
|
|
506
|
+
Returns:
|
|
507
|
+
argparse.Namespace: Parsed args.
|
|
508
|
+
"""
|
|
509
|
+
parser = argparse.ArgumentParser(
|
|
510
|
+
prog="reflexio-bench-retrieval",
|
|
511
|
+
description="Retrieval latency benchmark (profile / playbook / unified).",
|
|
512
|
+
)
|
|
513
|
+
parser.add_argument(
|
|
514
|
+
"--sizes",
|
|
515
|
+
type=_parse_sizes,
|
|
516
|
+
default=list(DEFAULT_SIZES),
|
|
517
|
+
help="Comma-separated corpus sizes (default: 100,1000,10000).",
|
|
518
|
+
)
|
|
519
|
+
parser.add_argument(
|
|
520
|
+
"--trials",
|
|
521
|
+
type=int,
|
|
522
|
+
default=DEFAULT_TRIALS,
|
|
523
|
+
help="Timed samples per cell (default: 50).",
|
|
524
|
+
)
|
|
525
|
+
parser.add_argument(
|
|
526
|
+
"--warmup",
|
|
527
|
+
type=int,
|
|
528
|
+
default=DEFAULT_WARMUP,
|
|
529
|
+
help="Untimed warmup invocations per cell (default: 5).",
|
|
530
|
+
)
|
|
531
|
+
parser.add_argument(
|
|
532
|
+
"--backend",
|
|
533
|
+
type=str,
|
|
534
|
+
default=",".join(DEFAULT_BACKENDS),
|
|
535
|
+
help="Comma-separated backends (default: sqlite,supabase).",
|
|
536
|
+
)
|
|
537
|
+
parser.add_argument(
|
|
538
|
+
"--layer",
|
|
539
|
+
type=str,
|
|
540
|
+
default=",".join(DEFAULT_LAYERS),
|
|
541
|
+
help="Comma-separated layers (default: service,http).",
|
|
542
|
+
)
|
|
543
|
+
parser.add_argument(
|
|
544
|
+
"--retrieval",
|
|
545
|
+
type=str,
|
|
546
|
+
default=",".join(DEFAULT_RETRIEVALS),
|
|
547
|
+
help="Comma-separated retrieval types (default: all four).",
|
|
548
|
+
)
|
|
549
|
+
parser.add_argument(
|
|
550
|
+
"--output-dir",
|
|
551
|
+
type=Path,
|
|
552
|
+
default=None,
|
|
553
|
+
help="Directory for results.json + report.md. "
|
|
554
|
+
f"Default: {_DEFAULT_OUTPUT_ROOT}/<timestamp>/",
|
|
555
|
+
)
|
|
556
|
+
parser.add_argument(
|
|
557
|
+
"--baseline",
|
|
558
|
+
type=Path,
|
|
559
|
+
default=None,
|
|
560
|
+
help="Optional baseline results.json to diff the report against.",
|
|
561
|
+
)
|
|
562
|
+
return parser.parse_args(argv)
|
|
563
|
+
|
|
564
|
+
|
|
565
|
+
def main(argv: list[str] | None = None) -> int:
|
|
566
|
+
"""
|
|
567
|
+
CLI entry point: parse args, run the sweep, write outputs.
|
|
568
|
+
|
|
569
|
+
Args:
|
|
570
|
+
argv (list[str] | None): Optional override of sys.argv.
|
|
571
|
+
|
|
572
|
+
Returns:
|
|
573
|
+
int: Exit code — 0 on success, 1 on a skipped-every-backend run.
|
|
574
|
+
"""
|
|
575
|
+
logging.basicConfig(
|
|
576
|
+
level=logging.INFO,
|
|
577
|
+
format="%(asctime)s %(levelname)s %(name)s: %(message)s",
|
|
578
|
+
)
|
|
579
|
+
args = _parse_args(argv)
|
|
580
|
+
|
|
581
|
+
backends = _parse_csv_list(args.backend, DEFAULT_BACKENDS)
|
|
582
|
+
layers = cast(list[Layer], _parse_csv_list(args.layer, DEFAULT_LAYERS))
|
|
583
|
+
retrievals = cast(
|
|
584
|
+
list[RetrievalType], _parse_csv_list(args.retrieval, DEFAULT_RETRIEVALS)
|
|
585
|
+
)
|
|
586
|
+
|
|
587
|
+
embed_cache = QueryEmbedCache()
|
|
588
|
+
embed_cache.ensure(QUERIES)
|
|
589
|
+
|
|
590
|
+
raw: list[dict[str, Any]] = []
|
|
591
|
+
with ExitStack() as stack:
|
|
592
|
+
for backend_name in backends:
|
|
593
|
+
handle = stack.enter_context(BACKENDS[backend_name]())
|
|
594
|
+
if handle is None:
|
|
595
|
+
logger.warning("Skipping backend %s (unavailable)", backend_name)
|
|
596
|
+
continue
|
|
597
|
+
raw.extend(
|
|
598
|
+
_run_for_backend(
|
|
599
|
+
handle=handle,
|
|
600
|
+
sizes=args.sizes,
|
|
601
|
+
layers=layers,
|
|
602
|
+
retrievals=retrievals,
|
|
603
|
+
trials=args.trials,
|
|
604
|
+
warmup=args.warmup,
|
|
605
|
+
embed_cache=embed_cache,
|
|
606
|
+
)
|
|
607
|
+
)
|
|
608
|
+
|
|
609
|
+
if not raw:
|
|
610
|
+
logger.error("No rows collected — every backend was skipped.")
|
|
611
|
+
return 1
|
|
612
|
+
|
|
613
|
+
stats = aggregate(raw)
|
|
614
|
+
timestamp = datetime.now(UTC).strftime("%Y-%m-%d_%H%M%S")
|
|
615
|
+
output_dir = args.output_dir or _DEFAULT_OUTPUT_ROOT / timestamp
|
|
616
|
+
results = RunResults(
|
|
617
|
+
config={
|
|
618
|
+
"timestamp": timestamp,
|
|
619
|
+
"git_sha": _git_sha(),
|
|
620
|
+
"org_id": BENCH_ORG_ID,
|
|
621
|
+
"sizes": args.sizes,
|
|
622
|
+
"trials": args.trials,
|
|
623
|
+
"warmup": args.warmup,
|
|
624
|
+
"backends": backends,
|
|
625
|
+
"layers": layers,
|
|
626
|
+
"retrievals": retrievals,
|
|
627
|
+
},
|
|
628
|
+
raw=raw,
|
|
629
|
+
stats=stats,
|
|
630
|
+
)
|
|
631
|
+
write_results_json(results, output_dir / "results.json")
|
|
632
|
+
baseline = load_baseline(args.baseline) if args.baseline else {}
|
|
633
|
+
(output_dir / "report.md").write_text(render_markdown(results, baseline))
|
|
634
|
+
logger.info(
|
|
635
|
+
"Wrote %s and %s", output_dir / "results.json", output_dir / "report.md"
|
|
636
|
+
)
|
|
637
|
+
print(json.dumps({"status": "ok", "output_dir": str(output_dir)}))
|
|
638
|
+
return 0
|
|
639
|
+
|
|
640
|
+
|
|
641
|
+
if __name__ == "__main__":
|
|
642
|
+
sys.exit(main())
|