This is an automated email from the ASF dual-hosted git repository.
imbajin pushed a commit to branch goal-test
in repository https://gitbox.apache.org/repos/asf/hugegraph-ai.git
The following commit(s) were added to refs/heads/goal-test by this push:
new b851072d fix(llm): address updated PR review findings
b851072d is described below
commit b851072df679f47ec3d4a7bd725af8fdd70beb2b
Author: imbajin <[email protected]>
AuthorDate: Mon Jun 1 21:39:58 2026 +0800
fix(llm): address updated PR review findings
- remove import-time repo-root probing from config paths
- synchronize /config/llm selectors across chat/extract/text2gql
- tighten HugeGraph smoke isolation and exact assertions
- enforce coverage floors while keeping readable action versions
---
.github/workflows/hugegraph-llm.yml | 40 +++++++++----------
.github/workflows/hugegraph-python-client.yml | 28 +++++++-------
.workflow/quality-program/quality-state.json | 45 +++++++++++++++++++++-
.../reports/final-quality-report.md | 27 +++++++++++--
.../reports/production-change-ledger.md | 6 ++-
docs/quality/coverage-ratchet.md | 11 ++++++
hugegraph-llm/src/hugegraph_llm/api/rag_api.py | 2 +
.../src/hugegraph_llm/config/models/base_config.py | 29 +++++++++++++-
.../config/models/base_prompt_config.py | 16 ++++++--
.../hugegraph_llm/demo/rag_demo/configs_block.py | 3 +-
hugegraph-llm/src/tests/api/test_rag_api.py | 9 ++++-
hugegraph-llm/src/tests/config/test_config.py | 15 ++++++++
hugegraph-llm/src/tests/conftest.py | 14 +++++++
.../src/tests/integration/test_core_kg_smoke.py | 37 +++++++++++++++++-
.../tests/integration/test_graph_rag_pipeline.py | 4 ++
.../src/tests/integration/test_kg_construction.py | 4 ++
.../src/tests/integration/test_rag_pipeline.py | 4 ++
17 files changed, 243 insertions(+), 51 deletions(-)
diff --git a/.github/workflows/hugegraph-llm.yml
b/.github/workflows/hugegraph-llm.yml
index b73d48ac..85fe694b 100644
--- a/.github/workflows/hugegraph-llm.yml
+++ b/.github/workflows/hugegraph-llm.yml
@@ -38,22 +38,22 @@ jobs:
python-version: ["3.10", "3.11"]
steps:
- - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
+ - uses: actions/checkout@v6
with:
persist-credentials: false
- name: Set up Python ${{ matrix.python-version }}
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065
+ uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
- name: Install uv
- run: |
- curl -LsSf https://astral.sh/uv/install.sh | sh
- echo "$HOME/.cargo/bin" >> $GITHUB_PATH
+ uses: astral-sh/setup-uv@v8
+ with:
+ version: "0.9.22"
- name: Cache dependencies
- uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830
+ uses: actions/cache@v5
with:
path: |
~/.cache/uv
@@ -71,10 +71,10 @@ jobs:
env:
SKIP_EXTERNAL_SERVICES: true
run: |
- uv run pytest hugegraph-llm/src/tests -m "unit or contract"
--cov=hugegraph_llm --cov-report=term
--cov-report=xml:.workflow/quality-program/coverage/llm-unit-contract.xml -q
+ uv run pytest hugegraph-llm/src/tests -m "unit or contract"
--cov=hugegraph_llm --cov-fail-under=34 --cov-report=term
--cov-report=xml:.workflow/quality-program/coverage/llm-unit-contract.xml -q
- name: Upload coverage artifact
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
+ uses: actions/upload-artifact@v7
with:
name: llm-unit-contract-coverage-${{ matrix.python-version }}
path: .workflow/quality-program/coverage/llm-unit-contract.xml
@@ -97,22 +97,22 @@ jobs:
- 8080:8080
steps:
- - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
+ - uses: actions/checkout@v6
with:
persist-credentials: false
- name: Set up Python ${{ matrix.python-version }}
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065
+ uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
- name: Install uv
- run: |
- curl -LsSf https://astral.sh/uv/install.sh | sh
- echo "$HOME/.cargo/bin" >> $GITHUB_PATH
+ uses: astral-sh/setup-uv@v8
+ with:
+ version: "0.9.22"
- name: Cache dependencies
- uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830
+ uses: actions/cache@v5
with:
path: |
~/.cache/uv
@@ -154,22 +154,22 @@ jobs:
- 8080:8080
steps:
- - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
+ - uses: actions/checkout@v6
with:
persist-credentials: false
- name: Set up Python ${{ matrix.python-version }}
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065
+ uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
- name: Install uv
- run: |
- curl -LsSf https://astral.sh/uv/install.sh | sh
- echo "$HOME/.cargo/bin" >> $GITHUB_PATH
+ uses: astral-sh/setup-uv@v8
+ with:
+ version: "0.9.22"
- name: Cache dependencies
- uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830
+ uses: actions/cache@v5
with:
path: |
~/.cache/uv
diff --git a/.github/workflows/hugegraph-python-client.yml
b/.github/workflows/hugegraph-python-client.yml
index 9017b69e..1a34bdd5 100644
--- a/.github/workflows/hugegraph-python-client.yml
+++ b/.github/workflows/hugegraph-python-client.yml
@@ -19,23 +19,23 @@ jobs:
python-version: ["3.10", "3.11", "3.12"]
steps:
- - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
+ - uses: actions/checkout@v6
with:
persist-credentials: false
- name: Set up Python ${{ matrix.python-version }}
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065
+ uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
- name: Install uv
- run: |
- curl -LsSf https://astral.sh/uv/install.sh | sh
- echo "$HOME/.cargo/bin" >> $GITHUB_PATH
+ uses: astral-sh/setup-uv@v8
+ with:
+ version: "0.9.22"
- name: Cache dependencies
id: cache-deps
- uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830
+ uses: actions/cache@v5
with:
path: |
~/.cache/uv
@@ -49,10 +49,10 @@ jobs:
- name: Run unit and contract tests
run: |
- uv run pytest hugegraph-python-client/src/tests -m "unit or
contract" --cov=pyhugegraph --cov-report=term
--cov-report=xml:.workflow/quality-program/coverage/client-unit-contract.xml -q
+ uv run pytest hugegraph-python-client/src/tests -m "unit or
contract" --cov=pyhugegraph --cov-fail-under=45 --cov-report=term
--cov-report=xml:.workflow/quality-program/coverage/client-unit-contract.xml -q
- name: Upload coverage artifact
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
+ uses: actions/upload-artifact@v7
with:
name: client-unit-contract-coverage-${{ matrix.python-version }}
path: .workflow/quality-program/coverage/client-unit-contract.xml
@@ -75,23 +75,23 @@ jobs:
- 8080:8080
steps:
- - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
+ - uses: actions/checkout@v6
with:
persist-credentials: false
- name: Set up Python ${{ matrix.python-version }}
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065
+ uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
- name: Install uv
- run: |
- curl -LsSf https://astral.sh/uv/install.sh | sh
- echo "$HOME/.cargo/bin" >> $GITHUB_PATH
+ uses: astral-sh/setup-uv@v8
+ with:
+ version: "0.9.22"
- name: Cache dependencies
id: cache-deps
- uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830
+ uses: actions/cache@v5
with:
path: |
~/.cache/uv
diff --git a/.workflow/quality-program/quality-state.json
b/.workflow/quality-program/quality-state.json
index c3fd5b4b..28de62ba 100644
--- a/.workflow/quality-program/quality-state.json
+++ b/.workflow/quality-program/quality-state.json
@@ -78,6 +78,9 @@
"hugegraph-llm/src/tests/operators/hugegraph_op/test_fetch_graph_data.py",
"hugegraph-llm/src/tests/operators/hugegraph_op/test_schema_manager.py",
"hugegraph-llm/src/hugegraph_llm/api/rag_api.py",
+ "hugegraph-llm/src/hugegraph_llm/config/models/base_config.py",
+ "hugegraph-llm/src/hugegraph_llm/config/models/base_prompt_config.py",
+ "hugegraph-llm/src/hugegraph_llm/demo/rag_demo/configs_block.py",
"hugegraph-llm/src/tests/fixtures/fake_llm.py",
"hugegraph-llm/src/tests/models/embeddings/test_ollama_embedding.py",
"hugegraph-llm/src/tests/data/quality_program/kg_text.txt",
@@ -87,6 +90,9 @@
"hugegraph-llm/src/tests/integration/test_core_kg_smoke.py",
"hugegraph-llm/src/tests/integration/test_core_graphrag_smoke.py",
"hugegraph-llm/src/tests/integration/test_core_text2gremlin_smoke.py",
+ "hugegraph-llm/src/tests/integration/test_graph_rag_pipeline.py",
+ "hugegraph-llm/src/tests/integration/test_kg_construction.py",
+ "hugegraph-llm/src/tests/integration/test_rag_pipeline.py",
"docs/quality/coverage-ratchet.md",
".workflow/quality-program/coverage/combined-baseline.json",
".workflow/quality-program/checkpoints/07-coverage-ratchet.md",
@@ -112,6 +118,30 @@
"file": "hugegraph-llm/src/hugegraph_llm/api/rag_api.py",
"change": "Map /config/llm to llm_settings.chat_llm_type instead of
nonexistent llm_settings.llm_type.",
"test": "uv run pytest hugegraph-llm/src/tests/api -m 'unit or contract'
-v --tb=short"
+ },
+ {
+ "goal": "PR68 updated review",
+ "file": "hugegraph-llm/src/hugegraph_llm/config/models/base_config.py",
+ "change": "Resolve .env through HUGEGRAPH_LLM_ENV_PATH, source-tree
module root, then cwd fallback without import-time repository-root probing.",
+ "test": "uv run pytest hugegraph-llm/src/tests/config/test_config.py -q"
+ },
+ {
+ "goal": "PR68 updated review",
+ "file":
"hugegraph-llm/src/hugegraph_llm/config/models/base_prompt_config.py",
+ "change": "Resolve prompt config YAML through package resources with a
module-relative fallback.",
+ "test": "uv run pytest hugegraph-llm/src/tests/config/test_config.py -q"
+ },
+ {
+ "goal": "PR68 updated review",
+ "file": "hugegraph-llm/src/hugegraph_llm/api/rag_api.py",
+ "change": "Keep /config/llm as one endpoint and synchronize chat,
extract, and Text2Gremlin LLM selectors.",
+ "test": "uv run pytest hugegraph-llm/src/tests/api/test_rag_api.py -q"
+ },
+ {
+ "goal": "PR68 updated review",
+ "file": "hugegraph-llm/src/hugegraph_llm/demo/rag_demo/configs_block.py",
+ "change": "Reuse the shared .env path from base_config for Gradio LLM
config propagation.",
+ "test": "uv run pytest hugegraph-llm/src/tests/config/test_config.py -q"
}
],
"tests_added_or_changed": [
@@ -125,7 +155,10 @@
"Added FakeLLM fixture and deterministic parser/operator tests for
property graph, keyword, and Gremlin generation contracts.",
"Added API public-surface tests for config field mapping, invalid request
bodies, and callback exception responses.",
"Added provider wrapper tests for OpenAI, LiteLLM, and Ollama
malformed/error surfaces.",
- "Added deterministic KG, GraphRAG, and Text2Gremlin smoke tests that
import production code."
+ "Added deterministic KG, GraphRAG, and Text2Gremlin smoke tests that
import production code.",
+ "Tightened KG smoke assertions to exact vertex and edge contents after
fixture cleanup.",
+ "Marked legacy mock-only integration suites as external and slow so
default gates do not silently leave ambiguous integration files outside the
selected layers.",
+ "Added config/API regression tests for package-relative config resolution,
shared demo .env path, and /config/llm selector synchronization."
],
"commands_run": [
"sed -n '1,220p' AGENTS.md",
@@ -212,7 +245,15 @@
"placeholder scan over .workflow/quality-program docs/quality",
"git status --short",
"uv run ruff format --check .",
- "uv run ruff check ."
+ "uv run ruff check .",
+ "uv run pytest hugegraph-llm/src/tests/config/test_config.py
hugegraph-llm/src/tests/api/test_rag_api.py -q",
+ "uv run pytest hugegraph-python-client/src/tests -m \"unit or contract\"
--cov=pyhugegraph --cov-fail-under=45 --cov-report=term
--cov-report=xml:.workflow/quality-program/coverage/client-unit-contract.xml
-q",
+ "uv run pytest hugegraph-llm/src/tests -m \"unit or contract\"
--cov=hugegraph_llm --cov-fail-under=34 --cov-report=term
--cov-report=xml:.workflow/quality-program/coverage/llm-unit-contract.xml -q",
+ "uv run python -c \"import yaml, pathlib;
[yaml.safe_load(pathlib.Path(p).read_text()) for p in
['.github/workflows/hugegraph-llm.yml','.github/workflows/hugegraph-python-client.yml']]\"",
+ "HUGEGRAPH_REQUIRED=true HUGEGRAPH_URL=http://127.0.0.1:18080
HUGEGRAPH_PASSWORD=admin uv run pytest
hugegraph-llm/src/tests/integration/test_hugegraph_boundary.py
hugegraph-llm/src/tests/integration/test_core_kg_smoke.py -v --tb=short",
+ "HUGEGRAPH_REQUIRED=true HUGEGRAPH_URL=http://127.0.0.1:18080
HUGEGRAPH_PASSWORD=admin uv run pytest hugegraph-llm/src/tests -m \"integration
and hugegraph\" -v --tb=short",
+ "HUGEGRAPH_REQUIRED=true HUGEGRAPH_URL=http://127.0.0.1:18080
HUGEGRAPH_PASSWORD=admin uv run pytest hugegraph-llm/src/tests/integration -m
\"smoke\" -v --tb=short",
+ "uv run pytest hugegraph-llm/src/tests/integration -m 'smoke and not
hugegraph' -v --tb=short"
],
"known_failures": [],
"deferred_items": [
diff --git a/.workflow/quality-program/reports/final-quality-report.md
b/.workflow/quality-program/reports/final-quality-report.md
index 2906638e..a4a0c012 100644
--- a/.workflow/quality-program/reports/final-quality-report.md
+++ b/.workflow/quality-program/reports/final-quality-report.md
@@ -25,6 +25,14 @@ Layer D external opt-in only, not default PR gates
| Formatting | workspace | `uv run ruff format --check .` | 342 files already
formatted |
| Lint | workspace | `uv run ruff check .` | all checks passed |
+Post-PR68 updated-review verification:
+
+| Layer | Module | Command | Result |
+|---|---|---|---|
+| Layer A | `hugegraph-llm` config/API contracts | `uv run pytest
hugegraph-llm/src/tests/config/test_config.py
hugegraph-llm/src/tests/api/test_rag_api.py -q` | 11 passed |
+| Layer B/C | `hugegraph-llm` HugeGraph boundary + KG smoke |
`HUGEGRAPH_REQUIRED=true HUGEGRAPH_URL=http://127.0.0.1:18080
HUGEGRAPH_PASSWORD=admin uv run pytest
hugegraph-llm/src/tests/integration/test_hugegraph_boundary.py
hugegraph-llm/src/tests/integration/test_core_kg_smoke.py -v --tb=short` | 5
passed |
+| Layer C | `hugegraph-llm` non-HugeGraph smoke | `uv run pytest
hugegraph-llm/src/tests/integration -m "smoke and not hugegraph" -v --tb=short`
| 3 passed, 16 deselected |
+
## Coverage Baseline and Ratchets
Baseline artifacts:
@@ -37,6 +45,15 @@ Baseline artifacts:
The combined baseline required `--import-mode=importlib` because both
workspace packages expose `tests.conftest` during cross-package collection.
+CI now enforces the initial module floors in the default unit/contract jobs:
+
+| Workflow | Coverage gate |
+|---|---:|
+| `.github/workflows/hugegraph-python-client.yml` | `--cov-fail-under=45` |
+| `.github/workflows/hugegraph-llm.yml` | `--cov-fail-under=34` |
+
+Final local gate results: `pyhugegraph` reached 45.34%; `hugegraph_llm`
reached 39.41%.
+
Initial ratchet areas are documented in `docs/quality/coverage-ratchet.md`:
- `pyhugegraph`
@@ -75,9 +92,11 @@ Final G7 sanity checks:
| G3 |
`hugegraph-llm/src/hugegraph_llm/operators/hugegraph_op/commit_to_hugegraph.py`
| Map primary-key `label:value` edge endpoints to server-created VIDs and raise
explicit vertex creation errors. | `uv run pytest
hugegraph-llm/src/tests/operators/hugegraph_op/test_commit_to_hugegraph.py::TestCommit2Graph::test_load_into_graph_raises_explicit_error_when_vertex_creation_fails
-q`; `HUGEGRAPH_REQUIRED=true uv run pytest
hugegraph-llm/src/tests/integration/test_hugegraph_boundary.py -v - [...]
| G4 | `hugegraph-llm/src/hugegraph_llm/api/rag_api.py` | Map `/config/llm` to
`llm_settings.chat_llm_type`. | `uv run pytest hugegraph-llm/src/tests/api -m
"unit or contract" -v --tb=short` |
| PR68 review |
`hugegraph-llm/src/hugegraph_llm/operators/hugegraph_op/commit_to_hugegraph.py`
| Extend primary-key endpoint mapping to multi-key vertex labels. | `uv run
pytest
hugegraph-llm/src/tests/operators/hugegraph_op/test_commit_to_hugegraph_load_into_graph.py
-q` |
-| PR68 review |
`hugegraph-llm/src/hugegraph_llm/config/models/base_prompt_config.py` | Resolve
prompt config YAML from the package project root instead of process cwd. | `uv
run pytest hugegraph-llm/src/tests/config/test_config.py -q` |
-| PR68 review | `hugegraph-llm/src/hugegraph_llm/config/models/base_config.py`
| Resolve `.env` from the package project root instead of process cwd. | `uv
run pytest hugegraph-llm/src/tests/config/test_config.py -q` |
+| PR68 review |
`hugegraph-llm/src/hugegraph_llm/config/models/base_prompt_config.py` | Resolve
prompt config YAML from package resources with module-relative fallback,
avoiding repository-root probing at import time. | `uv run pytest
hugegraph-llm/src/tests/config/test_config.py -q` |
+| PR68 review | `hugegraph-llm/src/hugegraph_llm/config/models/base_config.py`
| Resolve `.env` from explicit override, source-tree module root, then cwd
fallback, avoiding repository-root probing at import time. | `uv run pytest
hugegraph-llm/src/tests/config/test_config.py -q` |
| PR68 second review | `hugegraph-python-client/src/pyhugegraph/utils/util.py`
| Preserve `NotAuthorizedError` for 401 responses in `ResponseValidation`. |
`uv run pytest
hugegraph-python-client/src/tests/api/test_response_validation.py -q` |
+| PR68 updated review | `hugegraph-llm/src/hugegraph_llm/api/rag_api.py` |
Synchronize `/config/llm` across chat, extraction, and Text2Gremlin selectors.
| `uv run pytest hugegraph-llm/src/tests/api/test_rag_api.py -q` |
+| PR68 updated review |
`hugegraph-llm/src/hugegraph_llm/demo/rag_demo/configs_block.py` | Reuse the
shared `.env` path helper for Gradio config propagation. | `uv run pytest
hugegraph-llm/src/tests/config/test_config.py -q` |
No production code changed in G5-G7. PR68 review fixes added the
production-code rows above.
@@ -87,7 +106,8 @@ No production code changed in G5-G7. PR68 review fixes added
the production-code
- Two LLM model tests remain skipped inside the Layer A selection; they are
explicit pytest skips, not service-bound silent skips.
- Layer B commands used local HugeGraph `hugegraph/hugegraph:1.7.0` and
`HUGEGRAPH_REQUIRED=true`.
- GraphRAG smoke emits known NLTK BLEU zero-overlap warnings for short
deterministic strings; assertions do not depend on BLEU score value.
-- Legacy mock-only integration tests remain documented as future cleanup. New
authoritative smoke tests import production code.
+- Legacy mock-only integration tests are explicitly marked `external` and
`slow`. New authoritative smoke tests import production code.
+- Local `hugegraph-quality` on port 8080 returned 401 for `admin/admin`
despite `PASSWORD=admin`; updated-review Layer B/C verification used the
preserved fresh HugeGraph 1.7.0 container on port 18080 instead.
## Deferred Refactors
@@ -107,6 +127,7 @@ Deferred items are documented in
`.workflow/quality-program/reports/deferred-ref
- HugeGraph integration jobs use `hugegraph/hugegraph:1.7.0` and selected
integration tests fail when the required service is unavailable.
- Smoke tests are deterministic and exercise production code at KG, GraphRAG,
and Text2Gremlin boundaries.
- Coverage ratchets start from local areas instead of imposing a
full-repository threshold.
+- GitHub Actions are kept on readable official major-version tags
(`actions/checkout@v6`, `actions/setup-python@v6`, `actions/cache@v5`,
`actions/upload-artifact@v7`, `astral-sh/setup-uv@v8`) per maintainer
preference; SHA-pinning review feedback is intentionally not adopted.
## Recommended Next Actions
diff --git a/.workflow/quality-program/reports/production-change-ledger.md
b/.workflow/quality-program/reports/production-change-ledger.md
index 5684375a..71267361 100644
--- a/.workflow/quality-program/reports/production-change-ledger.md
+++ b/.workflow/quality-program/reports/production-change-ledger.md
@@ -6,6 +6,8 @@
| G3 |
`hugegraph-llm/src/hugegraph_llm/operators/hugegraph_op/commit_to_hugegraph.py`
| Map primary-key `label:value` edge endpoints to server-created VIDs and raise
explicit vertex creation errors before accessing `.id`. | `uv run pytest
hugegraph-llm/src/tests/operators/hugegraph_op/test_commit_to_hugegraph.py::TestCommit2Graph::test_load_into_graph_raises_explicit_error_when_vertex_creation_fails
-q`; `HUGEGRAPH_REQUIRED=true uv run pytest
hugegraph-llm/src/tests/integration/test_hug [...]
| G4 | `hugegraph-llm/src/hugegraph_llm/api/rag_api.py` | Map `/config/llm` to
existing `llm_settings.chat_llm_type` instead of nonexistent
`llm_settings.llm_type`. | `uv run pytest hugegraph-llm/src/tests/api -m "unit
or contract" -v --tb=short` | API public-surface field mapping contract gap. |
Low; aligns route with existing config schema and leaves callback arguments
unchanged. |
| PR68 review |
`hugegraph-llm/src/hugegraph_llm/operators/hugegraph_op/commit_to_hugegraph.py`
| Extend primary-key endpoint mapping to multi-key vertex labels by joining
primary key values with `!`. | `uv run pytest
hugegraph-llm/src/tests/operators/hugegraph_op/test_commit_to_hugegraph_load_into_graph.py
-q` | Review-identified edge creation gap for multiple primary-key vertex IDs.
| Low; only broadens fallback mapping for existing primary-key schemas. |
-| PR68 review |
`hugegraph-llm/src/hugegraph_llm/config/models/base_prompt_config.py` | Resolve
prompt config YAML from the package project root instead of process cwd. | `uv
run pytest hugegraph-llm/src/tests/config/test_config.py -q` | Avoid
import-time cwd mutation in test harness and make config path deterministic. |
Medium-low; preserves the same file path when run from module root and removes
cwd guard. |
-| PR68 review | `hugegraph-llm/src/hugegraph_llm/config/models/base_config.py`
| Resolve `.env` from the package project root instead of process cwd. | `uv
run pytest hugegraph-llm/src/tests/config/test_config.py -q` | Avoid writing or
reading a caller cwd `.env` when tests import config from repo root. |
Medium-low; preserves the same `.env` file when run from module root and
removes cwd coupling. |
+| PR68 review |
`hugegraph-llm/src/hugegraph_llm/config/models/base_prompt_config.py` | Resolve
prompt config YAML through package resources with a module-relative fallback,
avoiding import-time repository-root probing. | `uv run pytest
hugegraph-llm/src/tests/config/test_config.py -q` | Review-identified
packaged/vendored import failure when no parent `pyproject.toml` or `.git`
exists. | Medium-low; preserves the source-tree path and removes
`get_project_root()` from import-time prompt [...]
+| PR68 review | `hugegraph-llm/src/hugegraph_llm/config/models/base_config.py`
| Resolve `.env` through `HUGEGRAPH_LLM_ENV_PATH`, source-tree module root,
then process cwd fallback, avoiding import-time repository-root probing. | `uv
run pytest hugegraph-llm/src/tests/config/test_config.py -q` |
Review-identified packaged/vendored import failure when no parent
`pyproject.toml` or `.git` exists. | Medium-low; preserves source-tree `.env`
behavior while allowing explicit installed-layout o [...]
| PR68 second review | `hugegraph-python-client/src/pyhugegraph/utils/util.py`
| Preserve `NotAuthorizedError` for 401 responses in `ResponseValidation` while
keeping backend error-envelope details for other HTTP errors. | `uv run pytest
hugegraph-python-client/src/tests/api/test_response_validation.py -q` |
Second-review finding that the G2 envelope preservation broadened 401 responses
to generic `Exception`. | Low; restores the existing 401 contract and removes
dead HTTPError fallback code. |
+| PR68 updated review | `hugegraph-llm/src/hugegraph_llm/api/rag_api.py` |
Keep `/config/llm` as a single endpoint and synchronize `chat_llm_type`,
`extract_llm_type`, and `text2gql_llm_type`. | `uv run pytest
hugegraph-llm/src/tests/api/test_rag_api.py -q` | Review-identified runtime
regression where extractor and Text2Gremlin LLM selectors kept stale provider
values. | Medium-low; preserves current single-endpoint API contract and only
broadens selector synchronization. |
+| PR68 updated review |
`hugegraph-llm/src/hugegraph_llm/demo/rag_demo/configs_block.py` | Reuse the
shared `.env` path from `base_config` when deciding whether chat settings
should propagate to mini-task LLM settings. | `uv run pytest
hugegraph-llm/src/tests/config/test_config.py -q` | Review-identified
config-surface mismatch between API/config model and Gradio UI. | Low; removes
cwd-specific `.env` lookup from the demo config UI. |
diff --git a/docs/quality/coverage-ratchet.md b/docs/quality/coverage-ratchet.md
index 17c83d0f..8251cb13 100644
--- a/docs/quality/coverage-ratchet.md
+++ b/docs/quality/coverage-ratchet.md
@@ -33,6 +33,17 @@ Current combined baseline:
The original combined command hits a pytest import-path collision because both
workspace packages define a `tests.conftest` module. Use
`--import-mode=importlib` for combined workspace baselines until the test
package layout is normalized.
+## CI Gates
+
+The default unit/contract jobs enforce module-level floors from the initial
baseline artifacts:
+
+| Workflow | Scope | Gate |
+|---|---|---:|
+| `.github/workflows/hugegraph-python-client.yml` | `pyhugegraph`
unit/contract | `--cov-fail-under=45` |
+| `.github/workflows/hugegraph-llm.yml` | `hugegraph_llm` unit/contract |
`--cov-fail-under=34` |
+
+These gates are intentionally baseline-level floors. Raise them only after the
corresponding local ratchet areas gain meaningful tests.
+
## Local Commands
```bash
diff --git a/hugegraph-llm/src/hugegraph_llm/api/rag_api.py
b/hugegraph-llm/src/hugegraph_llm/api/rag_api.py
index bce7de0d..4f5a80c3 100644
--- a/hugegraph-llm/src/hugegraph_llm/api/rag_api.py
+++ b/hugegraph-llm/src/hugegraph_llm/api/rag_api.py
@@ -162,6 +162,8 @@ def rag_http_api(
@router.post("/config/llm", status_code=status.HTTP_201_CREATED)
def llm_config_api(req: LLMConfigRequest):
llm_settings.chat_llm_type = req.llm_type
+ llm_settings.extract_llm_type = req.llm_type
+ llm_settings.text2gql_llm_type = req.llm_type
if req.llm_type == "openai":
res = apply_llm_conf(
diff --git a/hugegraph-llm/src/hugegraph_llm/config/models/base_config.py
b/hugegraph-llm/src/hugegraph_llm/config/models/base_config.py
index 6953166b..0e5ca609 100644
--- a/hugegraph-llm/src/hugegraph_llm/config/models/base_config.py
+++ b/hugegraph-llm/src/hugegraph_llm/config/models/base_config.py
@@ -17,15 +17,40 @@
import os
+from pathlib import Path
from dotenv import dotenv_values, set_key
from pydantic_settings import BaseSettings
-from hugegraph_llm.utils.anchor import get_project_root
from hugegraph_llm.utils.log import log
dir_name = os.path.dirname
-env_path = os.path.join(get_project_root(), ".env")
+ENV_PATH_ENV_VAR = "HUGEGRAPH_LLM_ENV_PATH"
+
+
+def _source_project_root() -> Path | None:
+ package_root = Path(__file__).resolve().parents[2]
+ if package_root.parent.name != "src":
+ return None
+ project_root = package_root.parent.parent
+ if (project_root / "pyproject.toml").exists():
+ return project_root
+ return None
+
+
+def resolve_env_path() -> str:
+ explicit_env_path = os.getenv(ENV_PATH_ENV_VAR)
+ if explicit_env_path:
+ return str(Path(explicit_env_path).expanduser())
+
+ project_root = _source_project_root()
+ if project_root is not None:
+ return str(project_root / ".env")
+
+ return str(Path.cwd() / ".env")
+
+
+env_path = resolve_env_path()
class BaseConfig(BaseSettings):
diff --git
a/hugegraph-llm/src/hugegraph_llm/config/models/base_prompt_config.py
b/hugegraph-llm/src/hugegraph_llm/config/models/base_prompt_config.py
index b7cd2f91..feab61b3 100644
--- a/hugegraph-llm/src/hugegraph_llm/config/models/base_prompt_config.py
+++ b/hugegraph-llm/src/hugegraph_llm/config/models/base_prompt_config.py
@@ -16,16 +16,26 @@
# under the License.
import os
+from importlib import resources
+from pathlib import Path
import yaml
-from hugegraph_llm.utils.anchor import get_project_root
from hugegraph_llm.utils.log import log
dir_name = os.path.dirname
F_NAME = "config_prompt.yaml"
-PROJECT_ROOT = get_project_root()
-yaml_file_path = os.path.join(PROJECT_ROOT,
"src/hugegraph_llm/resources/demo", F_NAME)
+
+
+def resolve_prompt_yaml_path() -> str:
+ try:
+ return
str(resources.files("hugegraph_llm.resources.demo").joinpath(F_NAME))
+ except (ModuleNotFoundError, TypeError):
+ package_root = Path(__file__).resolve().parents[2]
+ return str(package_root / "resources" / "demo" / F_NAME)
+
+
+yaml_file_path = resolve_prompt_yaml_path()
class LiteralStr(str):
diff --git a/hugegraph-llm/src/hugegraph_llm/demo/rag_demo/configs_block.py
b/hugegraph-llm/src/hugegraph_llm/demo/rag_demo/configs_block.py
index 72c1eec0..0b51aa6c 100644
--- a/hugegraph-llm/src/hugegraph_llm/demo/rag_demo/configs_block.py
+++ b/hugegraph-llm/src/hugegraph_llm/demo/rag_demo/configs_block.py
@@ -16,7 +16,6 @@
# under the License.
import json
-import os
from functools import partial
from typing import Optional
@@ -26,6 +25,7 @@ from dotenv import dotenv_values
from requests.auth import HTTPBasicAuth
from hugegraph_llm.config import huge_settings, index_settings, llm_settings
+from hugegraph_llm.config.models.base_config import env_path
from hugegraph_llm.models.embeddings.litellm import LiteLLMEmbedding
from hugegraph_llm.models.llms.litellm import LiteLLMClient
from hugegraph_llm.utils.log import log
@@ -429,7 +429,6 @@ def create_configs_block() -> list:
llm_config_button = gr.Button("Apply configuration")
llm_config_button.click(apply_llm_config_with_chat_op,
inputs=llm_config_input)
# Determine whether there are Settings in the.env file
- env_path = os.path.join(os.getcwd(), ".env") # Load .env from
the current working directory
env_vars = dotenv_values(env_path)
api_extract_key = env_vars.get("OPENAI_EXTRACT_API_KEY")
api_text2sql_key = env_vars.get("OPENAI_TEXT2GQL_API_KEY")
diff --git a/hugegraph-llm/src/tests/api/test_rag_api.py
b/hugegraph-llm/src/tests/api/test_rag_api.py
index 336216fb..0bed3174 100644
--- a/hugegraph-llm/src/tests/api/test_rag_api.py
+++ b/hugegraph-llm/src/tests/api/test_rag_api.py
@@ -22,6 +22,7 @@ from fastapi import APIRouter, FastAPI, status
from fastapi.testclient import TestClient
from hugegraph_llm.api.rag_api import rag_http_api
+from hugegraph_llm.config import llm_settings
pytestmark = pytest.mark.contract
@@ -83,7 +84,10 @@ def
test_graph_config_api_passes_graph_field_to_apply_graph_conf():
)
-def test_llm_config_api_passes_openai_fields_to_apply_llm_conf():
+def test_llm_config_api_passes_openai_fields_to_apply_llm_conf(monkeypatch):
+ monkeypatch.setattr(llm_settings, "chat_llm_type", "ollama/local")
+ monkeypatch.setattr(llm_settings, "extract_llm_type", "ollama/local")
+ monkeypatch.setattr(llm_settings, "text2gql_llm_type", "ollama/local")
client, callbacks = _make_test_client()
response = client.post(
@@ -97,6 +101,9 @@ def
test_llm_config_api_passes_openai_fields_to_apply_llm_conf():
},
)
+ assert llm_settings.chat_llm_type == "openai"
+ assert llm_settings.extract_llm_type == "openai"
+ assert llm_settings.text2gql_llm_type == "openai"
assert response.status_code == status.HTTP_201_CREATED
assert response.json() == {"message": "Connection successful. Configured
finished."}
callbacks["apply_llm_conf"].assert_called_once_with(
diff --git a/hugegraph-llm/src/tests/config/test_config.py
b/hugegraph-llm/src/tests/config/test_config.py
index b5569a8f..e407194e 100644
--- a/hugegraph-llm/src/tests/config/test_config.py
+++ b/hugegraph-llm/src/tests/config/test_config.py
@@ -17,7 +17,9 @@
import unittest
+from os import environ
from pathlib import Path
+from unittest.mock import patch
import pytest
@@ -44,3 +46,16 @@ class TestConfig(unittest.TestCase):
expected = Path(__file__).resolve().parents[3] / ".env"
self.assertEqual(Path(base_config.env_path), expected)
+
+ def test_env_path_prefers_explicit_override(self):
+ from hugegraph_llm.config.models import base_config
+
+ custom_env = Path("/tmp/hugegraph-llm-test.env")
+ with patch.dict(environ, {base_config.ENV_PATH_ENV_VAR:
str(custom_env)}):
+ self.assertEqual(Path(base_config.resolve_env_path()), custom_env)
+
+ def test_demo_config_block_uses_shared_env_path(self):
+ from hugegraph_llm.config.models import base_config
+ from hugegraph_llm.demo.rag_demo import configs_block
+
+ self.assertEqual(configs_block.env_path, base_config.env_path)
diff --git a/hugegraph-llm/src/tests/conftest.py
b/hugegraph-llm/src/tests/conftest.py
index a8764547..a330280f 100644
--- a/hugegraph-llm/src/tests/conftest.py
+++ b/hugegraph-llm/src/tests/conftest.py
@@ -18,6 +18,7 @@
import logging
import os
import sys
+from contextlib import suppress
import nltk
import pytest
@@ -36,6 +37,17 @@ from fixtures.hugegraph_service import hugegraph_service #
noqa: E402
__all__ = ["hugegraph_client", "hugegraph_service"]
+def _clear_quality_schema(client):
+ schema = client.schema()
+ for remove in (
+ lambda: schema.edgeLabel("quality_created").remove(),
+ lambda: schema.vertexLabel("quality_software").remove(),
+ lambda: schema.vertexLabel("quality_person").remove(),
+ ):
+ with suppress(Exception):
+ remove()
+
+
@pytest.fixture()
def hugegraph_client(hugegraph_service):
from pyhugegraph.client import PyHugeClient
@@ -63,11 +75,13 @@ def hugegraph_client(hugegraph_service):
graphspace=hugegraph_service.graphspace,
)
client.graphs().clear_graph_all_data()
+ _clear_quality_schema(client)
try:
yield client
finally:
try:
client.graphs().clear_graph_all_data()
+ _clear_quality_schema(client)
finally:
for key, value in original.items():
setattr(huge_settings, key, value)
diff --git a/hugegraph-llm/src/tests/integration/test_core_kg_smoke.py
b/hugegraph-llm/src/tests/integration/test_core_kg_smoke.py
index ed505921..2824a9f5 100644
--- a/hugegraph-llm/src/tests/integration/test_core_kg_smoke.py
+++ b/hugegraph-llm/src/tests/integration/test_core_kg_smoke.py
@@ -71,5 +71,38 @@ def
test_kg_construction_smoke_uses_production_code(hugegraph_client):
Commit2Graph().run(data)
summary = FetchGraphData(hugegraph_client).run({})
- assert summary["vertex_num"] >= len(fixture["vertices"])
- assert summary["edge_num"] >= len(fixture["edges"])
+ vertices = hugegraph_client.gremlin().exec(
+ """
+ g.V().hasLabel('quality_person', 'quality_software').
+ project('label', 'name', 'age', 'lang').
+ by(label()).
+ by(values('name')).
+ by(coalesce(values('age'), constant(null))).
+ by(coalesce(values('lang'), constant(null)))
+ """
+ )["data"]
+ edges = hugegraph_client.gremlin().exec(
+ """
+ g.E().hasLabel('quality_created').
+ project('label', 'out', 'in', 'date').
+ by(label()).
+ by(outV().values('name')).
+ by(inV().values('name')).
+ by(values('date'))
+ """
+ )["data"]
+
+ assert summary["vertex_num"] == len(fixture["vertices"])
+ assert summary["edge_num"] == len(fixture["edges"])
+ assert sorted(vertices, key=lambda item: item["label"]) == [
+ {"label": "quality_person", "name": "marko", "age": 29, "lang": None},
+ {"label": "quality_software", "name": "lop", "age": None, "lang":
"java"},
+ ]
+ assert edges == [
+ {
+ "label": "quality_created",
+ "out": "marko",
+ "in": "lop",
+ "date": "2026-05-31",
+ }
+ ]
diff --git a/hugegraph-llm/src/tests/integration/test_graph_rag_pipeline.py
b/hugegraph-llm/src/tests/integration/test_graph_rag_pipeline.py
index 243963c3..8a352e29 100644
--- a/hugegraph-llm/src/tests/integration/test_graph_rag_pipeline.py
+++ b/hugegraph-llm/src/tests/integration/test_graph_rag_pipeline.py
@@ -21,8 +21,12 @@ import tempfile
import unittest
from unittest.mock import MagicMock
+import pytest
+
from tests.utils.mock import MockEmbedding
+pytestmark = [pytest.mark.external, pytest.mark.slow]
+
class BaseLLM:
def generate(self, prompt, **kwargs):
diff --git a/hugegraph-llm/src/tests/integration/test_kg_construction.py
b/hugegraph-llm/src/tests/integration/test_kg_construction.py
index daa7b191..379cb350 100644
--- a/hugegraph-llm/src/tests/integration/test_kg_construction.py
+++ b/hugegraph-llm/src/tests/integration/test_kg_construction.py
@@ -22,6 +22,8 @@ import os
import unittest
from unittest.mock import patch
+import pytest
+
# 导入测试工具
from src.tests.test_utils import (
create_test_document,
@@ -29,6 +31,8 @@ from src.tests.test_utils import (
with_mock_openai_client,
)
+pytestmark = [pytest.mark.external, pytest.mark.slow]
+
# Create mock classes to replace missing modules
class OpenAILLM:
diff --git a/hugegraph-llm/src/tests/integration/test_rag_pipeline.py
b/hugegraph-llm/src/tests/integration/test_rag_pipeline.py
index bb5e4364..3abf253f 100644
--- a/hugegraph-llm/src/tests/integration/test_rag_pipeline.py
+++ b/hugegraph-llm/src/tests/integration/test_rag_pipeline.py
@@ -19,6 +19,8 @@ import os
import tempfile
import unittest
+import pytest
+
# 导入测试工具
from src.tests.test_utils import (
create_test_document,
@@ -28,6 +30,8 @@ from src.tests.test_utils import (
)
from tests.utils.mock import VectorIndex
+pytestmark = [pytest.mark.external, pytest.mark.slow]
+
# 创建模拟类,替代缺失的模块
class Document: