Skip to content

Latest commit

 

History

History
130 lines (103 loc) · 7.86 KB

File metadata and controls

130 lines (103 loc) · 7.86 KB

AGENTS.md

1. Architecture

Stayquery is a Python 3.12 hybrid RAG evaluator for hospitality data.

  • Postgres is the authoritative write-side store for source records, normalized tables, query runs, retrieval hits, and documents chunks.
  • Qdrant is a derived read-side vector index. It must be rebuildable from Postgres documents.
  • OpenAI is used for structured query planning, embeddings, and grounded answer generation.
  • Typer exposes the CLI in stayquery.cli; stayquery.rag.answer_query is the stable app boundary for ask flows.
  • SQLAlchemy models define the database shape, and Alembic applies migrations.
  • Every user query produces one hybrid answer. SQL and vector retrieval are internal inputs to hybrid fusion, not standalone answer modes.

2. Repository map

  • src/stayquery/: application package.
    • service.py: orchestrates planning, SQL retrieval, vector retrieval, hybrid fusion, answer generation, and run persistence.
    • sql_retrieval.py: compiles a constrained QuerySpec into safe SQLAlchemy filters.
    • vector.py: maintains the Qdrant index and rehydrates vector hits from Postgres documents.
    • hybrid.py: merges SQL and vector rankings with reciprocal rank fusion.
    • ingest.py: validates seed JSON, upserts relational rows, chunks documents, and optionally indexes vectors.
    • source_api.py: syncs external Aminess API records into local seed JSON files before ingest.
    • chunking.py: converts source JSON records into stable multilingual document chunks.
    • schemas.py: Pydantic contracts for query specs, retrieval hits, answers, and ingest results.
    • openai_client.py: OpenAI wrapper for strict structured planning, embeddings, and grounded answers.
    • models.py, db.py, config.py, cli.py: persistence, runtime settings, and command-line entrypoints.
  • tests/: unit and contract tests for CLI behavior, schema validation, chunking, OpenAI schema strictness, retrieval safety, and eval fixtures.
  • tests/fixtures/questions.yaml: evaluation questions used by stayquery eval.
  • data/raw/: tracked fake/reference records and validation schemas used by tests; may be ingested explicitly for test scenarios.
  • data/novigrad/: current private real-data source; ignored by Git and never committed.
  • data/korcula/: private local output for Korcula records synced from the external Aminess API; ignored by Git and never committed.
  • migrations/: Alembic environment and schema revision.
  • docker-compose.yml: local Postgres and Qdrant services.
  • pyproject.toml: package metadata, dependencies, CLI script, pytest, and Ruff settings.
  • README.md: user-facing setup and usage guide.
  • uv.lock: locked dependency graph; keep it in sync when dependencies change.

3. Development workflow

Use uv for Python environment and command execution.

docker compose up -d postgres qdrant
uv sync --all-extras
uv run stayquery db upgrade
uv run stayquery ingest --data path/to/data --skip-vector
uv run stayquery sync-api --destination korcula --out data/korcula --skip-vector

The --skip-vector ingest path validates schemas and writes Postgres rows without requiring OpenAI credentials.

Set OPENAI_API_KEY only when running embeddings or answer generation. Full RAG flows are:

uv run stayquery ingest --data path/to/data
uv run stayquery ask "Which options are good for a family that needs beach access?"
uv run stayquery eval --questions tests/fixtures/questions.yaml

When changing dependencies, update pyproject.toml and refresh uv.lock with uv lock.

4. Testing requirements

Run the test suite before handing off changes:

uv run pytest

Targeted expectations:

  • Retrieval changes must preserve bound SQL parameters and the hybrid fallback to vector hits when SQL returns zero hits.
  • Schema and chunking changes must preserve seed validation, multilingual text flattening, stable doc_id, and stable content_hash.
  • CLI changes must preserve the hybrid answer output, fallback display, warnings, and timing summary.
  • OpenAI planning schema changes must preserve strict structured output compatibility.
  • Ingest or migration changes should also be smoke-tested with uv run stayquery ingest --data path/to/data --skip-vector against a deliberately selected local dataset when Postgres is available.
  • Source API sync changes should preserve configurable Aminess API settings, ignored private output under data/korcula, and reuse the normal ingest validation path.

5. Agent-specific rules

  • Inspect the existing code and tests before editing.
  • Keep changes scoped to the requested behavior; avoid unrelated refactors and metadata churn.
  • Do not overwrite user changes or revert files unless explicitly asked.
  • Never commit secrets, .env, API keys, local cache directories, or service data.
  • Prefer rg and rg --files for search.
  • Prefer existing project patterns over new abstractions.
  • Use uv run ... for project commands.
  • Avoid raw SQL unless there is a clear need; prefer SQLAlchemy expressions and models.
  • Add or update tests when behavior changes.
  • Keep comments and docstrings useful: explain non-obvious intent, not line-by-line mechanics.

6. RAG-specific constraints

  • LLM planning may produce only a QuerySpec; it must never produce executable SQL.
  • SQL retrieval must compile QuerySpec into SQLAlchemy expressions with bound parameters.
  • Postgres documents are authoritative for retrieval evidence. Qdrant is a derived index only.
  • Vector retrieval must rehydrate Qdrant hits from Postgres before returning evidence.
  • Skip stale vector hits when the Postgres document is missing or the Qdrant content_hash no longer matches.
  • Hybrid retrieval uses reciprocal rank fusion over SQL and vector hits.
  • If SQL returns zero hits, hybrid retrieval falls back to vector hits and records sql_zero_hits.
  • Generated answers must use only the supplied evidence and cite source ids in the form source_file#section_path.
  • Keep SQL and vector retrieval internal to hybrid evidence selection so evaluation measures the app's final hybrid answer.

7. Documentation requirements

  • At the end of each run, explicitly update every relevant file affected by the final diff, including code, tests, fixtures, docs, schemas, migrations, config, and changelog entries when they apply.
  • Update README.md when setup commands, CLI usage, environment variables, service dependencies, or workflow expectations change.
  • Update fixtures or evaluation notes when adding, removing, or materially changing evaluation questions.
  • Document data shape changes when source JSON schemas, chunk metadata, or ingest behavior changes.
  • Document migration implications when database tables, columns, indexes, or persistence behavior change.
  • Update docs cross-links when adding, removing, renaming, or materially changing documentation pages.
  • Keep AGENTS.md current when agent workflow, testing expectations, or RAG invariants change.

8. After every coding task

After making the code change:

  1. Review the git diff.
  2. Identify every relevant file implied by the diff, not only the file that was directly requested.
  3. Update all affected code, tests, fixtures, docs, schemas, migrations, config, and changelog entries needed to keep the repository coherent.
  4. Update all affected documentation according to Documentation requirements.
  5. If architecture changed, update docs/architecture and create or update an ADR.
  6. If API behavior changed, update docs/api.
  7. If config/env/deployment changed, update docs/operations.
  8. If auth/security/data handling changed, update docs/security.
  9. If developer commands changed, update README.md or docs/development.
  10. Update PROGRESS.md by adding new follow-up tasks discovered during the run and changing existing task statuses when work has started or completed.
  11. If no related files need updates, state the reason explicitly.

Do not finish until documentation has been checked against the final diff.