homegraph 1.1.2 → 1.2.0
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/LICENSE +21 -21
- package/README.md +268 -243
- package/dist/arkts/ohos-api-index.d.ts +15 -0
- package/dist/arkts/ohos-api-index.d.ts.map +1 -0
- package/dist/arkts/ohos-api-index.js +190 -0
- package/dist/arkts/ohos-api-index.js.map +1 -0
- package/dist/arkts/ohos-sdk-input.d.ts +36 -0
- package/dist/arkts/ohos-sdk-input.d.ts.map +1 -0
- package/dist/arkts/ohos-sdk-input.js +214 -0
- package/dist/arkts/ohos-sdk-input.js.map +1 -0
- package/dist/bin/command-supervision.d.ts +12 -0
- package/dist/bin/command-supervision.d.ts.map +1 -0
- package/dist/bin/command-supervision.js +86 -0
- package/dist/bin/command-supervision.js.map +1 -0
- package/dist/bin/homegraph.d.ts +1 -1
- package/dist/bin/homegraph.js +971 -71
- package/dist/bin/homegraph.js.map +1 -1
- package/dist/db/index.d.ts +20 -0
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +39 -0
- package/dist/db/index.js.map +1 -1
- package/dist/db/migrations.d.ts +1 -1
- package/dist/db/migrations.d.ts.map +1 -1
- package/dist/db/migrations.js +58 -19
- package/dist/db/migrations.js.map +1 -1
- package/dist/db/queries.d.ts +14 -0
- package/dist/db/queries.d.ts.map +1 -1
- package/dist/db/queries.js +314 -143
- package/dist/db/queries.js.map +1 -1
- package/dist/db/schema.sql +172 -152
- package/dist/directory.d.ts +32 -0
- package/dist/directory.d.ts.map +1 -1
- package/dist/directory.js +88 -5
- package/dist/directory.js.map +1 -1
- package/dist/extraction/arkts-batch-worker.d.ts +2 -0
- package/dist/extraction/arkts-batch-worker.d.ts.map +1 -0
- package/dist/extraction/arkts-batch-worker.js +28 -0
- package/dist/extraction/arkts-batch-worker.js.map +1 -0
- package/dist/extraction/context.d.ts +11 -0
- package/dist/extraction/context.d.ts.map +1 -1
- package/dist/extraction/context.js +20 -0
- package/dist/extraction/context.js.map +1 -1
- package/dist/extraction/index.d.ts +16 -2
- package/dist/extraction/index.d.ts.map +1 -1
- package/dist/extraction/index.js +619 -380
- package/dist/extraction/index.js.map +1 -1
- package/dist/extraction/languages/arkts-state-decorators.d.ts +13 -0
- package/dist/extraction/languages/arkts-state-decorators.d.ts.map +1 -0
- package/dist/extraction/languages/arkts-state-decorators.js +26 -0
- package/dist/extraction/languages/arkts-state-decorators.js.map +1 -0
- package/dist/extraction/languages/arkts-viewtree.d.ts +4 -2
- package/dist/extraction/languages/arkts-viewtree.d.ts.map +1 -1
- package/dist/extraction/languages/arkts-viewtree.js +21 -6
- package/dist/extraction/languages/arkts-viewtree.js.map +1 -1
- package/dist/extraction/languages/arkts.d.ts +98 -2
- package/dist/extraction/languages/arkts.d.ts.map +1 -1
- package/dist/extraction/languages/arkts.js +1290 -61
- package/dist/extraction/languages/arkts.js.map +1 -1
- package/dist/extraction/languages/c-cpp.d.ts +56 -0
- package/dist/extraction/languages/c-cpp.d.ts.map +1 -1
- package/dist/extraction/languages/c-cpp.js +198 -1
- package/dist/extraction/languages/c-cpp.js.map +1 -1
- package/dist/extraction/languages/ohos-api-consumer.d.ts +34 -0
- package/dist/extraction/languages/ohos-api-consumer.d.ts.map +1 -0
- package/dist/extraction/languages/ohos-api-consumer.js +283 -0
- package/dist/extraction/languages/ohos-api-consumer.js.map +1 -0
- package/dist/extraction/parse-pool.d.ts +126 -0
- package/dist/extraction/parse-pool.d.ts.map +1 -0
- package/dist/extraction/parse-pool.js +319 -0
- package/dist/extraction/parse-pool.js.map +1 -0
- package/dist/extraction/tree-sitter-types.d.ts +17 -0
- package/dist/extraction/tree-sitter-types.d.ts.map +1 -1
- package/dist/extraction/tree-sitter.d.ts +21 -0
- package/dist/extraction/tree-sitter.d.ts.map +1 -1
- package/dist/extraction/tree-sitter.js +198 -27
- package/dist/extraction/tree-sitter.js.map +1 -1
- package/dist/extraction/wasm/tree-sitter-c_sharp.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-pascal.wasm +0 -0
- package/dist/graph/traversal.d.ts.map +1 -1
- package/dist/graph/traversal.js +76 -17
- package/dist/graph/traversal.js.map +1 -1
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +78 -4
- package/dist/index.js.map +1 -1
- package/dist/installer/instructions-template.js +9 -9
- package/dist/installer/targets/shared.d.ts +5 -6
- package/dist/installer/targets/shared.d.ts.map +1 -1
- package/dist/installer/targets/shared.js +5 -6
- package/dist/installer/targets/shared.js.map +1 -1
- package/dist/mcp/daemon-paths.d.ts +30 -3
- package/dist/mcp/daemon-paths.d.ts.map +1 -1
- package/dist/mcp/daemon-paths.js +50 -10
- package/dist/mcp/daemon-paths.js.map +1 -1
- package/dist/mcp/daemon-registry.d.ts.map +1 -1
- package/dist/mcp/daemon-registry.js +7 -3
- package/dist/mcp/daemon-registry.js.map +1 -1
- package/dist/mcp/daemon.d.ts +48 -0
- package/dist/mcp/daemon.d.ts.map +1 -1
- package/dist/mcp/daemon.js +196 -32
- package/dist/mcp/daemon.js.map +1 -1
- package/dist/mcp/engine.d.ts +17 -0
- package/dist/mcp/engine.d.ts.map +1 -1
- package/dist/mcp/engine.js +73 -1
- package/dist/mcp/engine.js.map +1 -1
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +25 -43
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/liveness-watchdog.js +16 -16
- package/dist/mcp/ppid-watchdog.d.ts +18 -0
- package/dist/mcp/ppid-watchdog.d.ts.map +1 -1
- package/dist/mcp/ppid-watchdog.js +37 -0
- package/dist/mcp/ppid-watchdog.js.map +1 -1
- package/dist/mcp/query-cache.d.ts +25 -0
- package/dist/mcp/query-cache.d.ts.map +1 -0
- package/dist/mcp/query-cache.js +191 -0
- package/dist/mcp/query-cache.js.map +1 -0
- package/dist/mcp/query-pool.d.ts +94 -0
- package/dist/mcp/query-pool.d.ts.map +1 -0
- package/dist/mcp/query-pool.js +297 -0
- package/dist/mcp/query-pool.js.map +1 -0
- package/dist/mcp/query-worker.d.ts +24 -0
- package/dist/mcp/query-worker.d.ts.map +1 -0
- package/dist/mcp/query-worker.js +87 -0
- package/dist/mcp/query-worker.js.map +1 -0
- package/dist/mcp/server-instructions.d.ts +5 -7
- package/dist/mcp/server-instructions.d.ts.map +1 -1
- package/dist/mcp/server-instructions.js +72 -74
- package/dist/mcp/server-instructions.js.map +1 -1
- package/dist/mcp/tools.d.ts +94 -4
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.js +877 -71
- package/dist/mcp/tools.js.map +1 -1
- package/dist/project-config.d.ts +20 -0
- package/dist/project-config.d.ts.map +1 -1
- package/dist/project-config.js +42 -2
- package/dist/project-config.js.map +1 -1
- package/dist/reasoning/login.js +1 -1
- package/dist/reasoning/login.js.map +1 -1
- package/dist/reasoning/reasoner.js +32 -32
- package/dist/resolution/c-fnptr-synthesizer.d.ts +0 -28
- package/dist/resolution/c-fnptr-synthesizer.d.ts.map +1 -1
- package/dist/resolution/c-fnptr-synthesizer.js +765 -79
- package/dist/resolution/c-fnptr-synthesizer.js.map +1 -1
- package/dist/resolution/callback-synthesizer.d.ts +1 -1
- package/dist/resolution/callback-synthesizer.d.ts.map +1 -1
- package/dist/resolution/callback-synthesizer.js +72 -11
- package/dist/resolution/callback-synthesizer.js.map +1 -1
- package/dist/resolution/cooperative-yield.d.ts +32 -0
- package/dist/resolution/cooperative-yield.d.ts.map +1 -0
- package/dist/resolution/cooperative-yield.js +42 -0
- package/dist/resolution/cooperative-yield.js.map +1 -0
- package/dist/resolution/index.d.ts +11 -2
- package/dist/resolution/index.d.ts.map +1 -1
- package/dist/resolution/index.js +72 -4
- package/dist/resolution/index.js.map +1 -1
- package/dist/resolution/name-matcher.d.ts +22 -0
- package/dist/resolution/name-matcher.d.ts.map +1 -1
- package/dist/resolution/name-matcher.js +317 -20
- package/dist/resolution/name-matcher.js.map +1 -1
- package/dist/spec/config.d.ts +39 -0
- package/dist/spec/config.d.ts.map +1 -0
- package/dist/spec/config.js +304 -0
- package/dist/spec/config.js.map +1 -0
- package/dist/spec/db/commit-node.d.ts +23 -0
- package/dist/spec/db/commit-node.d.ts.map +1 -0
- package/dist/spec/db/commit-node.js +62 -0
- package/dist/spec/db/commit-node.js.map +1 -0
- package/dist/spec/db/fragment-node.d.ts +24 -0
- package/dist/spec/db/fragment-node.d.ts.map +1 -0
- package/dist/spec/db/fragment-node.js +128 -0
- package/dist/spec/db/fragment-node.js.map +1 -0
- package/dist/spec/db/fts.d.ts +74 -0
- package/dist/spec/db/fts.d.ts.map +1 -0
- package/dist/spec/db/fts.js +324 -0
- package/dist/spec/db/fts.js.map +1 -0
- package/dist/spec/db/index.d.ts +13 -0
- package/dist/spec/db/index.d.ts.map +1 -0
- package/dist/spec/db/index.js +50 -0
- package/dist/spec/db/index.js.map +1 -0
- package/dist/spec/db/relations.d.ts +55 -0
- package/dist/spec/db/relations.d.ts.map +1 -0
- package/dist/spec/db/relations.js +158 -0
- package/dist/spec/db/relations.js.map +1 -0
- package/dist/spec/db/schema.d.ts +33 -0
- package/dist/spec/db/schema.d.ts.map +1 -0
- package/dist/spec/db/schema.js +119 -0
- package/dist/spec/db/schema.js.map +1 -0
- package/dist/spec/db/schema.sql +117 -0
- package/dist/spec/db/spec-node.d.ts +41 -0
- package/dist/spec/db/spec-node.d.ts.map +1 -0
- package/dist/spec/db/spec-node.js +114 -0
- package/dist/spec/db/spec-node.js.map +1 -0
- package/dist/spec/evolve/impact-locator.d.ts +13 -0
- package/dist/spec/evolve/impact-locator.d.ts.map +1 -0
- package/dist/spec/evolve/impact-locator.js +25 -0
- package/dist/spec/evolve/impact-locator.js.map +1 -0
- package/dist/spec/evolve/llm-client.d.ts +50 -0
- package/dist/spec/evolve/llm-client.d.ts.map +1 -0
- package/dist/spec/evolve/llm-client.js +176 -0
- package/dist/spec/evolve/llm-client.js.map +1 -0
- package/dist/spec/evolve/logic-checker.d.ts +12 -0
- package/dist/spec/evolve/logic-checker.d.ts.map +1 -0
- package/dist/spec/evolve/logic-checker.js +24 -0
- package/dist/spec/evolve/logic-checker.js.map +1 -0
- package/dist/spec/evolve/pipeline.d.ts +42 -0
- package/dist/spec/evolve/pipeline.d.ts.map +1 -0
- package/dist/spec/evolve/pipeline.js +567 -0
- package/dist/spec/evolve/pipeline.js.map +1 -0
- package/dist/spec/evolve/spec-rewriter.d.ts +42 -0
- package/dist/spec/evolve/spec-rewriter.d.ts.map +1 -0
- package/dist/spec/evolve/spec-rewriter.js +230 -0
- package/dist/spec/evolve/spec-rewriter.js.map +1 -0
- package/dist/spec/graph/queries.d.ts +155 -0
- package/dist/spec/graph/queries.d.ts.map +1 -0
- package/dist/spec/graph/queries.js +440 -0
- package/dist/spec/graph/queries.js.map +1 -0
- package/dist/spec/llm/client.d.ts +29 -0
- package/dist/spec/llm/client.d.ts.map +1 -0
- package/dist/spec/llm/client.js +123 -0
- package/dist/spec/llm/client.js.map +1 -0
- package/dist/spec/llm/index.d.ts +3 -0
- package/dist/spec/llm/index.d.ts.map +1 -0
- package/dist/spec/llm/index.js +11 -0
- package/dist/spec/llm/index.js.map +1 -0
- package/dist/spec/llm/prompts.d.ts +13 -0
- package/dist/spec/llm/prompts.d.ts.map +1 -0
- package/dist/spec/llm/prompts.js +75 -0
- package/dist/spec/llm/prompts.js.map +1 -0
- package/dist/spec/mining/diff-parser.d.ts +33 -0
- package/dist/spec/mining/diff-parser.d.ts.map +1 -0
- package/dist/spec/mining/diff-parser.js +166 -0
- package/dist/spec/mining/diff-parser.js.map +1 -0
- package/dist/spec/mining/git-scanner.d.ts +103 -0
- package/dist/spec/mining/git-scanner.d.ts.map +1 -0
- package/dist/spec/mining/git-scanner.js +307 -0
- package/dist/spec/mining/git-scanner.js.map +1 -0
- package/dist/spec/mining/pipeline.d.ts +53 -0
- package/dist/spec/mining/pipeline.d.ts.map +1 -0
- package/dist/spec/mining/pipeline.js +178 -0
- package/dist/spec/mining/pipeline.js.map +1 -0
- package/dist/spec/mining/scope-resolver.d.ts +45 -0
- package/dist/spec/mining/scope-resolver.d.ts.map +1 -0
- package/dist/spec/mining/scope-resolver.js +103 -0
- package/dist/spec/mining/scope-resolver.js.map +1 -0
- package/dist/spec/mining/spec-extractor.d.ts +69 -0
- package/dist/spec/mining/spec-extractor.d.ts.map +1 -0
- package/dist/spec/mining/spec-extractor.js +369 -0
- package/dist/spec/mining/spec-extractor.js.map +1 -0
- package/dist/spec/types.d.ts +149 -0
- package/dist/spec/types.d.ts.map +1 -0
- package/dist/spec/types.js +15 -0
- package/dist/spec/types.js.map +1 -0
- package/dist/spec/utils.d.ts +167 -0
- package/dist/spec/utils.d.ts.map +1 -0
- package/dist/spec/utils.js +463 -0
- package/dist/spec/utils.js.map +1 -0
- package/dist/sync/worktree.d.ts +9 -0
- package/dist/sync/worktree.d.ts.map +1 -1
- package/dist/sync/worktree.js +40 -0
- package/dist/sync/worktree.js.map +1 -1
- package/dist/types.d.ts +6 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/ui/shimmer-progress.d.ts +2 -0
- package/dist/ui/shimmer-progress.d.ts.map +1 -1
- package/dist/ui/shimmer-progress.js +19 -2
- package/dist/ui/shimmer-progress.js.map +1 -1
- package/dist/upgrade/index.js +1 -1
- package/dist/upgrade/index.js.map +1 -1
- package/package.json +58 -57
- package/scripts/add-lang/bench.sh +60 -60
- package/scripts/add-lang/check-grammar.mjs +75 -75
- package/scripts/add-lang/dump-ast.mjs +103 -103
- package/scripts/add-lang/verify-extraction.mjs +70 -70
- package/scripts/agent-eval/ab-adoption.sh +91 -91
- package/scripts/agent-eval/ab-hook.sh +86 -86
- package/scripts/agent-eval/ab-impl.sh +78 -78
- package/scripts/agent-eval/ab-new-vs-baseline.sh +102 -102
- package/scripts/agent-eval/ab-sufficiency.sh +78 -78
- package/scripts/agent-eval/arms-F.sh +21 -21
- package/scripts/agent-eval/arms-matrix.sh +37 -37
- package/scripts/agent-eval/audit.sh +68 -68
- package/scripts/agent-eval/bench-readme.sh +28 -28
- package/scripts/agent-eval/bench-why-repo.sh +22 -22
- package/scripts/agent-eval/block-read-hook.sh +19 -19
- package/scripts/agent-eval/hook-settings.json +15 -15
- package/scripts/agent-eval/itrun.sh +120 -120
- package/scripts/agent-eval/offload-eval-3arm.sh +72 -72
- package/scripts/agent-eval/offload-eval-cost.mjs +133 -133
- package/scripts/agent-eval/offload-eval-effort.mjs +108 -108
- package/scripts/agent-eval/offload-eval-frontload-matrix.sh +25 -25
- package/scripts/agent-eval/offload-eval-frontload.sh +47 -47
- package/scripts/agent-eval/offload-eval-ground-truth.json +18 -18
- package/scripts/agent-eval/offload-eval-hook.mjs +84 -84
- package/scripts/agent-eval/offload-eval-judge.mjs +103 -103
- package/scripts/agent-eval/offload-eval-matrix.sh +20 -20
- package/scripts/agent-eval/offload-eval-metrics.mjs +94 -94
- package/scripts/agent-eval/offload-eval-refs1.sh +50 -50
- package/scripts/agent-eval/offload-eval-setup.sh +24 -24
- package/scripts/agent-eval/offload-eval-styles.sh +71 -71
- package/scripts/agent-eval/offload-eval-summarize.mjs +68 -68
- package/scripts/agent-eval/offload-eval.md +76 -76
- package/scripts/agent-eval/parse-arms.mjs +116 -116
- package/scripts/agent-eval/parse-bench-readme.mjs +84 -84
- package/scripts/agent-eval/parse-run.mjs +45 -45
- package/scripts/agent-eval/parse-session.mjs +93 -93
- package/scripts/agent-eval/probe-context.mjs +21 -21
- package/scripts/agent-eval/probe-explore.mjs +40 -40
- package/scripts/agent-eval/probe-node.mjs +20 -20
- package/scripts/agent-eval/probe-sweep.mjs +119 -119
- package/scripts/agent-eval/probe-trace.mjs +20 -20
- package/scripts/agent-eval/redirect-read-hook.sh +38 -38
- package/scripts/agent-eval/repro-concurrent-explore.mjs +119 -0
- package/scripts/agent-eval/repro-daemon-clients.mjs +125 -0
- package/scripts/agent-eval/run-agent.sh +34 -34
- package/scripts/agent-eval/run-all.sh +69 -69
- package/scripts/agent-eval/run-arms.sh +56 -56
- package/scripts/agent-eval/seq-matrix.mjs +137 -137
- package/scripts/build-bundle.sh +118 -118
- package/scripts/exp_boundary_eval/README.md +247 -0
- package/scripts/exp_boundary_eval/__pycache__/_utils.cpython-310.pyc +0 -0
- package/scripts/exp_boundary_eval/__pycache__/analyze.cpython-310.pyc +0 -0
- package/scripts/exp_boundary_eval/__pycache__/deveco_arm.cpython-310.pyc +0 -0
- package/scripts/exp_boundary_eval/__pycache__/run_one.cpython-310.pyc +0 -0
- package/scripts/exp_boundary_eval/__pycache__/run_session.cpython-310.pyc +0 -0
- package/scripts/exp_boundary_eval/__pycache__/setup.cpython-310.pyc +0 -0
- package/scripts/exp_boundary_eval/_test_mcp_chain.py +78 -0
- package/scripts/exp_boundary_eval/_test_stdin.py +8 -0
- package/scripts/exp_boundary_eval/_utils.py +1116 -0
- package/scripts/exp_boundary_eval/analyze.py +1313 -0
- package/scripts/exp_boundary_eval/data/agents.json +109 -0
- package/scripts/exp_boundary_eval/data/experiments.json +140 -0
- package/scripts/exp_boundary_eval/deveco_arm.py +519 -0
- package/scripts/exp_boundary_eval/run_all.py +378 -0
- package/scripts/exp_boundary_eval/run_one.py +165 -0
- package/scripts/exp_boundary_eval/run_session.py +158 -0
- package/scripts/exp_boundary_eval/setup.py +120 -0
- package/scripts/exp_boundary_eval/win_mcp_launcher.py +73 -0
- package/scripts/exp_boundary_eval/win_mcp_stdio_wrap.js +36 -0
- package/scripts/exp_boundary_eval/win_node_launcher.py +24 -0
- package/scripts/extract-release-notes.mjs +130 -130
- package/scripts/local-install.sh +41 -41
- package/scripts/npm-sdk.js +75 -75
- package/scripts/npm-shim.js +268 -246
- package/scripts/ohos-sdk-publish.mjs +133 -0
- package/scripts/pack-npm.sh +119 -119
- package/scripts/prepare-release.mjs +270 -270
- package/scripts/qa_eval/README.md +407 -404
- package/scripts/qa_eval/_test_deveco_probe.py +41 -41
- package/scripts/qa_eval/agent_runner.py +526 -526
- package/scripts/qa_eval/data/.gitignore +4 -4
- package/scripts/qa_eval/data/test-set.jsonl +2 -22
- package/scripts/qa_eval/eval_metrics.py +274 -233
- package/scripts/qa_eval/external_agent.py +976 -671
- package/scripts/qa_eval/llm_config.py +92 -92
- package/scripts/qa_eval/memory_monitor.py +132 -132
- package/scripts/qa_eval/my_answer_accuracy.py +187 -187
- package/scripts/qa_eval/requirements.txt +2 -2
- package/scripts/qa_eval/run_pipeline.py +804 -711
- package/scripts/qa_eval/stats_efficiency.py +279 -279
- package/scripts/qa_eval/stats_scores.py +207 -207
|
@@ -1,187 +1,187 @@
|
|
|
1
|
-
"""LLM-as-Judge Answer Accuracy (0–1), dual-prompt average — standalone, no ragas."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
import logging
|
|
6
|
-
import math
|
|
7
|
-
import re
|
|
8
|
-
from dataclasses import dataclass
|
|
9
|
-
|
|
10
|
-
from openai import AsyncOpenAI
|
|
11
|
-
|
|
12
|
-
logger = logging.getLogger(__name__)
|
|
13
|
-
|
|
14
|
-
TEMPLATE_ACCURACY1 = (
|
|
15
|
-
"Instruction: You are an assistant for rating a User Answer given a Question. "
|
|
16
|
-
"The Question is fully answered by the Reference Answer.\n"
|
|
17
|
-
"Focus on whether the User Answer captures the key meaning and intent of the Reference Answer. "
|
|
18
|
-
"Minor wording differences, alternative phrasing, or extra irrelevant information should not lower the rating.\n"
|
|
19
|
-
"Say 5, if the User Answer conveys the same overall meaning and essential content as the Reference Answer.\n"
|
|
20
|
-
"Say 4, if the User Answer is mostly correct, broadly aligned with the Reference Answer, with only small omissions or slight issues.\n"
|
|
21
|
-
"Say 3, if the User Answer is reasonably correct, covering several important aspects of the Reference Answer, even if incomplete.\n"
|
|
22
|
-
"Say 2, if the User Answer shows some overlap, but misses many essential aspects.\n"
|
|
23
|
-
"Say 1, if the User Answer has very little overlap with the Reference Answer.\n"
|
|
24
|
-
"Say 0, if the User Answer does not address the question at all.\n"
|
|
25
|
-
"Do not explain or justify your rating. Your rating must be a single integer 0–5.\n"
|
|
26
|
-
"If the User Answer is empty, the rating is 0.\n"
|
|
27
|
-
"### Question: {query}\n"
|
|
28
|
-
"### {answer0}: {sentence_inference}\n"
|
|
29
|
-
"### {answer1}: {sentence_true}\n"
|
|
30
|
-
"The rating is:\n"
|
|
31
|
-
)
|
|
32
|
-
|
|
33
|
-
TEMPLATE_ACCURACY2 = (
|
|
34
|
-
"I will rate the User Answer in comparison to the Reference Answer for a given Question.\n"
|
|
35
|
-
"The evaluation must focus mainly on whether the User Answer conveys the essential meaning and intent of the Reference Answer. "
|
|
36
|
-
"Minor details, alternative phrasing, or extra content should not strongly affect the rating.\n"
|
|
37
|
-
"If the User Answer is empty, the rating is 0.\n"
|
|
38
|
-
"The scale is 0 to 5:\n"
|
|
39
|
-
"0 = Does not address the question at all\n"
|
|
40
|
-
"1 = Very limited overlap with the Reference Answer\n"
|
|
41
|
-
"2 = Some overlap, but misses many essential aspects\n"
|
|
42
|
-
"3 = Reasonably correct, covers several important aspects but incomplete\n"
|
|
43
|
-
"4 = Mostly correct, broadly aligned with the Reference Answer with only small gaps\n"
|
|
44
|
-
"5 = Fully correct, conveys the same overall meaning and essential content as the Reference Answer\n"
|
|
45
|
-
"I will provide the rating as a single integer 0–5 without explanation.\n\n"
|
|
46
|
-
"Question: {query}\n\n"
|
|
47
|
-
"{answer0}: {sentence_inference}\n\n"
|
|
48
|
-
"{answer1}: {sentence_true}\n\n"
|
|
49
|
-
"Rating: "
|
|
50
|
-
)
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
def remove_tool_calls(text: str) -> str:
|
|
54
|
-
"""Strip --- ... --- blocks that contain agent tool invocations before judging."""
|
|
55
|
-
pattern = re.compile(
|
|
56
|
-
r"---\s*[\s\S]*?"
|
|
57
|
-
r"(ReadFile|SearchText|ReadManyFiles|ReadFolder|SemanticSearch|FindFiles|Custom|HomegraphQuery|HomegraphExplore)"
|
|
58
|
-
r"[\s\S]*?---",
|
|
59
|
-
re.MULTILINE,
|
|
60
|
-
)
|
|
61
|
-
cleaned = re.sub(pattern, "", text)
|
|
62
|
-
return re.sub(r"\n{3,}", "\n\n", cleaned).strip()
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
def extract_json_blocks_answerbyCOT(text: str) -> str:
|
|
66
|
-
"""Remove redacted_thinking blocks from chain-of-thought model output."""
|
|
67
|
-
cleaned = re.sub(
|
|
68
|
-
r"<think>.*?</think>",
|
|
69
|
-
"",
|
|
70
|
-
text,
|
|
71
|
-
flags=re.DOTALL | re.IGNORECASE,
|
|
72
|
-
)
|
|
73
|
-
return cleaned.strip()
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
def process_score(response: str) -> float:
|
|
77
|
-
for i in range(6):
|
|
78
|
-
if str(i) in response.strip():
|
|
79
|
-
return i / 5
|
|
80
|
-
return math.nan
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
def average_scores(score0: float, score1: float) -> float:
|
|
84
|
-
if not math.isnan(score0) and not math.isnan(score1):
|
|
85
|
-
return (score0 + score1) / 2
|
|
86
|
-
if math.isnan(score0) and math.isnan(score1):
|
|
87
|
-
return math.nan
|
|
88
|
-
return score0 if math.isnan(score1) else score1
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
@dataclass
|
|
92
|
-
class MyAnswerAccuracy:
|
|
93
|
-
"""Dual-template LLM judge; scores normalized to 0–1."""
|
|
94
|
-
|
|
95
|
-
client: AsyncOpenAI
|
|
96
|
-
model: str
|
|
97
|
-
retry: int = 5
|
|
98
|
-
extra_body: dict | None = None
|
|
99
|
-
|
|
100
|
-
@classmethod
|
|
101
|
-
def create(
|
|
102
|
-
cls,
|
|
103
|
-
*,
|
|
104
|
-
api_key: str,
|
|
105
|
-
base_url: str,
|
|
106
|
-
model: str,
|
|
107
|
-
timeout_sec: float = 1800,
|
|
108
|
-
extra_body: dict | None = None,
|
|
109
|
-
) -> MyAnswerAccuracy:
|
|
110
|
-
client = AsyncOpenAI(api_key=api_key, base_url=base_url, timeout=timeout_sec)
|
|
111
|
-
return cls(client=client, model=model, extra_body=extra_body)
|
|
112
|
-
|
|
113
|
-
async def _chat(self, prompt: str) -> str:
|
|
114
|
-
kwargs: dict = {
|
|
115
|
-
"model": self.model,
|
|
116
|
-
"messages": [{"role": "user", "content": prompt}],
|
|
117
|
-
"temperature": 0.10,
|
|
118
|
-
}
|
|
119
|
-
if self.extra_body:
|
|
120
|
-
kwargs["extra_body"] = self.extra_body
|
|
121
|
-
resp = await self.client.chat.completions.create(**kwargs)
|
|
122
|
-
return (resp.choices[0].message.content or "").strip()
|
|
123
|
-
|
|
124
|
-
async def _rate(self, prompt: str) -> float:
|
|
125
|
-
for attempt in range(self.retry):
|
|
126
|
-
try:
|
|
127
|
-
text = await self._chat(prompt)
|
|
128
|
-
score = process_score(text)
|
|
129
|
-
if not math.isnan(score):
|
|
130
|
-
return score
|
|
131
|
-
except Exception as e:
|
|
132
|
-
logger.warning("Judge call failed (attempt %s): %s", attempt + 1, e)
|
|
133
|
-
logger.warning("Judge retry (invalid rating): %s", attempt + 1)
|
|
134
|
-
return math.nan
|
|
135
|
-
|
|
136
|
-
async def single_turn_ascore(
|
|
137
|
-
self,
|
|
138
|
-
*,
|
|
139
|
-
user_input: str,
|
|
140
|
-
response: str,
|
|
141
|
-
reference: str,
|
|
142
|
-
) -> float:
|
|
143
|
-
prompt1 = TEMPLATE_ACCURACY1.format(
|
|
144
|
-
query=user_input,
|
|
145
|
-
answer0="User Answer",
|
|
146
|
-
answer1="Reference Answer",
|
|
147
|
-
sentence_inference=response,
|
|
148
|
-
sentence_true=reference,
|
|
149
|
-
)
|
|
150
|
-
prompt2 = TEMPLATE_ACCURACY2.format(
|
|
151
|
-
query=user_input,
|
|
152
|
-
answer0="Reference Answer",
|
|
153
|
-
answer1="User Answer",
|
|
154
|
-
sentence_inference=reference,
|
|
155
|
-
sentence_true=response,
|
|
156
|
-
)
|
|
157
|
-
try:
|
|
158
|
-
s0 = await self._rate(prompt1)
|
|
159
|
-
s1 = await self._rate(prompt2)
|
|
160
|
-
return average_scores(s0, s1)
|
|
161
|
-
except Exception as e:
|
|
162
|
-
logger.warning("Judge error: %s", e)
|
|
163
|
-
return math.nan
|
|
164
|
-
|
|
165
|
-
async def evaluate_answer_accuracy_single(self, sample_data: dict) -> dict:
|
|
166
|
-
result = sample_data.copy()
|
|
167
|
-
try:
|
|
168
|
-
raw = str(sample_data.get("output_answer", ""))
|
|
169
|
-
raw = extract_json_blocks_answerbyCOT(raw)
|
|
170
|
-
response = remove_tool_calls(raw)
|
|
171
|
-
score = await self.single_turn_ascore(
|
|
172
|
-
user_input=str(sample_data.get("query", "")),
|
|
173
|
-
response=response,
|
|
174
|
-
reference=str(sample_data.get("reference_answer", "")),
|
|
175
|
-
)
|
|
176
|
-
result["answer_accuracy_score"] = float(score) if not math.isnan(score) else 0.0
|
|
177
|
-
result["evaluation_status"] = "success" if not math.isnan(score) else "failed"
|
|
178
|
-
if math.isnan(score):
|
|
179
|
-
result["error_message"] = "Judge 未返回有效 0–5 分数"
|
|
180
|
-
except Exception as e:
|
|
181
|
-
logger.error("评估答案准确性时出错: %s", e)
|
|
182
|
-
result["answer_accuracy_score"] = 0.0
|
|
183
|
-
result["evaluation_status"] = "error"
|
|
184
|
-
result["error_message"] = str(e)
|
|
185
|
-
|
|
186
|
-
result.pop("evaluation", None)
|
|
187
|
-
return result
|
|
1
|
+
"""LLM-as-Judge Answer Accuracy (0–1), dual-prompt average — standalone, no ragas."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
import math
|
|
7
|
+
import re
|
|
8
|
+
from dataclasses import dataclass
|
|
9
|
+
|
|
10
|
+
from openai import AsyncOpenAI
|
|
11
|
+
|
|
12
|
+
logger = logging.getLogger(__name__)
|
|
13
|
+
|
|
14
|
+
TEMPLATE_ACCURACY1 = (
|
|
15
|
+
"Instruction: You are an assistant for rating a User Answer given a Question. "
|
|
16
|
+
"The Question is fully answered by the Reference Answer.\n"
|
|
17
|
+
"Focus on whether the User Answer captures the key meaning and intent of the Reference Answer. "
|
|
18
|
+
"Minor wording differences, alternative phrasing, or extra irrelevant information should not lower the rating.\n"
|
|
19
|
+
"Say 5, if the User Answer conveys the same overall meaning and essential content as the Reference Answer.\n"
|
|
20
|
+
"Say 4, if the User Answer is mostly correct, broadly aligned with the Reference Answer, with only small omissions or slight issues.\n"
|
|
21
|
+
"Say 3, if the User Answer is reasonably correct, covering several important aspects of the Reference Answer, even if incomplete.\n"
|
|
22
|
+
"Say 2, if the User Answer shows some overlap, but misses many essential aspects.\n"
|
|
23
|
+
"Say 1, if the User Answer has very little overlap with the Reference Answer.\n"
|
|
24
|
+
"Say 0, if the User Answer does not address the question at all.\n"
|
|
25
|
+
"Do not explain or justify your rating. Your rating must be a single integer 0–5.\n"
|
|
26
|
+
"If the User Answer is empty, the rating is 0.\n"
|
|
27
|
+
"### Question: {query}\n"
|
|
28
|
+
"### {answer0}: {sentence_inference}\n"
|
|
29
|
+
"### {answer1}: {sentence_true}\n"
|
|
30
|
+
"The rating is:\n"
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
TEMPLATE_ACCURACY2 = (
|
|
34
|
+
"I will rate the User Answer in comparison to the Reference Answer for a given Question.\n"
|
|
35
|
+
"The evaluation must focus mainly on whether the User Answer conveys the essential meaning and intent of the Reference Answer. "
|
|
36
|
+
"Minor details, alternative phrasing, or extra content should not strongly affect the rating.\n"
|
|
37
|
+
"If the User Answer is empty, the rating is 0.\n"
|
|
38
|
+
"The scale is 0 to 5:\n"
|
|
39
|
+
"0 = Does not address the question at all\n"
|
|
40
|
+
"1 = Very limited overlap with the Reference Answer\n"
|
|
41
|
+
"2 = Some overlap, but misses many essential aspects\n"
|
|
42
|
+
"3 = Reasonably correct, covers several important aspects but incomplete\n"
|
|
43
|
+
"4 = Mostly correct, broadly aligned with the Reference Answer with only small gaps\n"
|
|
44
|
+
"5 = Fully correct, conveys the same overall meaning and essential content as the Reference Answer\n"
|
|
45
|
+
"I will provide the rating as a single integer 0–5 without explanation.\n\n"
|
|
46
|
+
"Question: {query}\n\n"
|
|
47
|
+
"{answer0}: {sentence_inference}\n\n"
|
|
48
|
+
"{answer1}: {sentence_true}\n\n"
|
|
49
|
+
"Rating: "
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def remove_tool_calls(text: str) -> str:
|
|
54
|
+
"""Strip --- ... --- blocks that contain agent tool invocations before judging."""
|
|
55
|
+
pattern = re.compile(
|
|
56
|
+
r"---\s*[\s\S]*?"
|
|
57
|
+
r"(ReadFile|SearchText|ReadManyFiles|ReadFolder|SemanticSearch|FindFiles|Custom|HomegraphQuery|HomegraphExplore)"
|
|
58
|
+
r"[\s\S]*?---",
|
|
59
|
+
re.MULTILINE,
|
|
60
|
+
)
|
|
61
|
+
cleaned = re.sub(pattern, "", text)
|
|
62
|
+
return re.sub(r"\n{3,}", "\n\n", cleaned).strip()
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def extract_json_blocks_answerbyCOT(text: str) -> str:
|
|
66
|
+
"""Remove redacted_thinking blocks from chain-of-thought model output."""
|
|
67
|
+
cleaned = re.sub(
|
|
68
|
+
r"<think>.*?</think>",
|
|
69
|
+
"",
|
|
70
|
+
text,
|
|
71
|
+
flags=re.DOTALL | re.IGNORECASE,
|
|
72
|
+
)
|
|
73
|
+
return cleaned.strip()
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def process_score(response: str) -> float:
|
|
77
|
+
for i in range(6):
|
|
78
|
+
if str(i) in response.strip():
|
|
79
|
+
return i / 5
|
|
80
|
+
return math.nan
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def average_scores(score0: float, score1: float) -> float:
|
|
84
|
+
if not math.isnan(score0) and not math.isnan(score1):
|
|
85
|
+
return (score0 + score1) / 2
|
|
86
|
+
if math.isnan(score0) and math.isnan(score1):
|
|
87
|
+
return math.nan
|
|
88
|
+
return score0 if math.isnan(score1) else score1
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
@dataclass
|
|
92
|
+
class MyAnswerAccuracy:
|
|
93
|
+
"""Dual-template LLM judge; scores normalized to 0–1."""
|
|
94
|
+
|
|
95
|
+
client: AsyncOpenAI
|
|
96
|
+
model: str
|
|
97
|
+
retry: int = 5
|
|
98
|
+
extra_body: dict | None = None
|
|
99
|
+
|
|
100
|
+
@classmethod
|
|
101
|
+
def create(
|
|
102
|
+
cls,
|
|
103
|
+
*,
|
|
104
|
+
api_key: str,
|
|
105
|
+
base_url: str,
|
|
106
|
+
model: str,
|
|
107
|
+
timeout_sec: float = 1800,
|
|
108
|
+
extra_body: dict | None = None,
|
|
109
|
+
) -> MyAnswerAccuracy:
|
|
110
|
+
client = AsyncOpenAI(api_key=api_key, base_url=base_url, timeout=timeout_sec)
|
|
111
|
+
return cls(client=client, model=model, extra_body=extra_body)
|
|
112
|
+
|
|
113
|
+
async def _chat(self, prompt: str) -> str:
|
|
114
|
+
kwargs: dict = {
|
|
115
|
+
"model": self.model,
|
|
116
|
+
"messages": [{"role": "user", "content": prompt}],
|
|
117
|
+
"temperature": 0.10,
|
|
118
|
+
}
|
|
119
|
+
if self.extra_body:
|
|
120
|
+
kwargs["extra_body"] = self.extra_body
|
|
121
|
+
resp = await self.client.chat.completions.create(**kwargs)
|
|
122
|
+
return (resp.choices[0].message.content or "").strip()
|
|
123
|
+
|
|
124
|
+
async def _rate(self, prompt: str) -> float:
|
|
125
|
+
for attempt in range(self.retry):
|
|
126
|
+
try:
|
|
127
|
+
text = await self._chat(prompt)
|
|
128
|
+
score = process_score(text)
|
|
129
|
+
if not math.isnan(score):
|
|
130
|
+
return score
|
|
131
|
+
except Exception as e:
|
|
132
|
+
logger.warning("Judge call failed (attempt %s): %s", attempt + 1, e)
|
|
133
|
+
logger.warning("Judge retry (invalid rating): %s", attempt + 1)
|
|
134
|
+
return math.nan
|
|
135
|
+
|
|
136
|
+
async def single_turn_ascore(
|
|
137
|
+
self,
|
|
138
|
+
*,
|
|
139
|
+
user_input: str,
|
|
140
|
+
response: str,
|
|
141
|
+
reference: str,
|
|
142
|
+
) -> float:
|
|
143
|
+
prompt1 = TEMPLATE_ACCURACY1.format(
|
|
144
|
+
query=user_input,
|
|
145
|
+
answer0="User Answer",
|
|
146
|
+
answer1="Reference Answer",
|
|
147
|
+
sentence_inference=response,
|
|
148
|
+
sentence_true=reference,
|
|
149
|
+
)
|
|
150
|
+
prompt2 = TEMPLATE_ACCURACY2.format(
|
|
151
|
+
query=user_input,
|
|
152
|
+
answer0="Reference Answer",
|
|
153
|
+
answer1="User Answer",
|
|
154
|
+
sentence_inference=reference,
|
|
155
|
+
sentence_true=response,
|
|
156
|
+
)
|
|
157
|
+
try:
|
|
158
|
+
s0 = await self._rate(prompt1)
|
|
159
|
+
s1 = await self._rate(prompt2)
|
|
160
|
+
return average_scores(s0, s1)
|
|
161
|
+
except Exception as e:
|
|
162
|
+
logger.warning("Judge error: %s", e)
|
|
163
|
+
return math.nan
|
|
164
|
+
|
|
165
|
+
async def evaluate_answer_accuracy_single(self, sample_data: dict) -> dict:
|
|
166
|
+
result = sample_data.copy()
|
|
167
|
+
try:
|
|
168
|
+
raw = str(sample_data.get("output_answer", ""))
|
|
169
|
+
raw = extract_json_blocks_answerbyCOT(raw)
|
|
170
|
+
response = remove_tool_calls(raw)
|
|
171
|
+
score = await self.single_turn_ascore(
|
|
172
|
+
user_input=str(sample_data.get("query", "")),
|
|
173
|
+
response=response,
|
|
174
|
+
reference=str(sample_data.get("reference_answer", "")),
|
|
175
|
+
)
|
|
176
|
+
result["answer_accuracy_score"] = float(score) if not math.isnan(score) else 0.0
|
|
177
|
+
result["evaluation_status"] = "success" if not math.isnan(score) else "failed"
|
|
178
|
+
if math.isnan(score):
|
|
179
|
+
result["error_message"] = "Judge 未返回有效 0–5 分数"
|
|
180
|
+
except Exception as e:
|
|
181
|
+
logger.error("评估答案准确性时出错: %s", e)
|
|
182
|
+
result["answer_accuracy_score"] = 0.0
|
|
183
|
+
result["evaluation_status"] = "error"
|
|
184
|
+
result["error_message"] = str(e)
|
|
185
|
+
|
|
186
|
+
result.pop("evaluation", None)
|
|
187
|
+
return result
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
openai>=1.40.0
|
|
2
|
-
tqdm>=4.66.0
|
|
1
|
+
openai>=1.40.0
|
|
2
|
+
tqdm>=4.66.0
|