Skip to content

[Phase 5] feat(ai): 법률 RAG 임베딩 적재 구현 - #25

Merged
HOKAGO-MEMORIES merged 2 commits into
developfrom
phase/5-legal-embedding-upsert
Jun 22, 2026
Merged

[Phase 5] feat(ai): 법률 RAG 임베딩 적재 구현#25
HOKAGO-MEMORIES merged 2 commits into
developfrom
phase/5-legal-embedding-upsert

Conversation

@HOKAGO-MEMORIES

@HOKAGO-MEMORIES HOKAGO-MEMORIES commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

변경 내용

  • 법률 문서 ingestion에 명시적 --write 모드를 추가했습니다.
  • prepared chunk를 embedding client로 임베딩한 뒤 Supabase pgvector 테이블에 upsert하는 경계를 추가했습니다.
  • content_hash conflict target 기반 idempotent upsert를 테스트했습니다.
  • phase5 하네스 문서를 추가했습니다.

연결 이슈

closes #24

테스트

  • cd backend-ai && .\.venv\Scripts\python.exe -m pytest tests
  • git diff --check

Summary by CodeRabbit

Release Notes

  • New Features

    • Legal document ingestion now supports embedding and writing chunk vectors to the database via an idempotent upsert (based on content hash).
    • The ingestion CLI adds a --write mode to perform database writes and prints ingestion counts; dry-run remains safe and read-only.
  • Tests

    • Added coverage for embedding→upsert flow, SQL/upsert behavior, output summaries, and enforced CLI mode handling.
  • Documentation

    • Added a phase specification for embedding and upsert requirements.

@coderabbitai

coderabbitai Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: cb74af03-3559-4a6a-82ee-a873e985fabb

📥 Commits

Reviewing files that changed from the base of the PR and between 6941836 and 765bdc0.

📒 Files selected for processing (2)
  • backend-ai/app/clients/supabase_client.py
  • backend-ai/tests/test_legal_ingestion_upsert.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • backend-ai/app/clients/supabase_client.py

📝 Walkthrough

Walkthrough

Implements Phase 5 of the legal RAG pipeline: adds upsert_legal_document_chunks to SupabaseVectorClient with ON CONFLICT (content_hash) idempotent upsert, adds embed_legal_chunks/write_legal_chunks orchestration functions to the ingestion script, gates the write path behind a new --write CLI flag, and covers the full path with offline TDD tests using fake clients.

Changes

Legal Embedding Upsert Pipeline

Layer / File(s) Summary
SupabaseVectorClient upsert method and parameter builder
backend-ai/app/clients/supabase_client.py
Adds upsert_legal_document_chunks executing INSERT ... ON CONFLICT (content_hash) DO UPDATE per row under statement_timeout, and legal_chunk_upsert_params validating embeddings, converting them to pgvector literals, and serializing metadata_json as JSONB-ready text.
Ingestion script write mode
backend-ai/scripts/ingest_legal_docs.py
Adds embed_legal_chunks and write_legal_chunks orchestration functions, a --write CLI flag mutually exclusive with --dry-run, optional embedding_client/vector_client injection in main(), and a write summary output path.
Tests: fake clients, unit, integration, and SQL validation
backend-ai/tests/test_legal_ingestion_upsert.py
Introduces FakeEmbeddingClient/FakeVectorClient, tests for embedding immutability, write_legal_chunks orchestration, CLI write mode output and exit code enforcement, monkeypatched psycopg SQL assertion for conflict targeting and parameter formatting, and a dry-run regression test.
Phase 5 specification
phases/ai-legal-rag/phase5-legal-embedding-upsert.md
Adds the phase specification describing done-when criteria, architecture rules, and TDD/offline test constraints.

Sequence Diagram(s)

sequenceDiagram
  actor CLI
  participant main
  participant write_legal_chunks
  participant embed_legal_chunks
  participant EmbeddingClient
  participant SupabaseVectorClient

  CLI->>main: --write --source <file>
  main->>write_legal_chunks: prepared rows, embedding_client, vector_client
  write_legal_chunks->>embed_legal_chunks: rows, embedding_client
  loop per chunk row
    embed_legal_chunks->>EmbeddingClient: embed_query(content)
    EmbeddingClient-->>embed_legal_chunks: embedding vector
  end
  embed_legal_chunks-->>write_legal_chunks: rows with embeddings
  write_legal_chunks->>SupabaseVectorClient: upsert_legal_document_chunks(embedded rows)
  SupabaseVectorClient-->>write_legal_chunks: upserted count
  write_legal_chunks-->>main: {chunks, upserted}
  main-->>CLI: print summary, exit 0
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • ssafy-salman/salmanhae#19: Introduced the dry-run chunk preparation pipeline and --dry-run CLI flag in ingest_legal_docs.py that this PR extends into a full write path with embedding and upsert.
  • ssafy-salman/salmanhae#21: Introduced EmbeddingClient boundary and phase 3 retriever that this PR reuses alongside the SupabaseVectorClient conventions for orchestrating embedding and storage.

Poem

🐇 Hop, hop, the chunks are here,
Embedded neat, the vectors appear!
content_hash guards each row with care,
No duplicate chunks, no reason to fear.
The dry-run stays safe — the write flag's the key,
Upserted to Supabase, pgvector-free! 🌟

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed Title references phase 5 and legal RAG embedding implementation, directly matching the PR content changes.
Description check ✅ Passed Description covers main changes, linked issue, and test execution details but lacks structured detail on each file change and review points.
Linked Issues check ✅ Passed All four requirements from issue #24 are met: dry-run preserved [upsert_legal_docs.py], TDD tests added [test_legal_ingestion_upsert.py], explicit --write mode added [ingest_legal_docs.py], Supabase upsert implemented [supabase_client.py].
Out of Scope Changes check ✅ Passed All changes directly support phase 5 objectives: SupabaseVectorClient upsert, embedding client integration, CLI --write mode, comprehensive tests, and phase documentation.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch phase/5-legal-embedding-upsert

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
backend-ai/tests/test_legal_ingestion_upsert.py (1)

172-190: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Align the test name with what is actually asserted.

At Line 172, the name says it verifies prepare_legal_chunks defaults embeddings to None, but the test only asserts dry-run returns 0. Rename it (or add assertions for the no-embedding invariant) to avoid misleading coverage.

Proposed minimal fix
-def test_prepare_legal_chunks_still_defaults_to_no_embedding(tmp_path) -> None:
+def test_dry_run_mode_returns_success(tmp_path) -> None:
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend-ai/tests/test_legal_ingestion_upsert.py` around lines 172 - 190, The
test function test_prepare_legal_chunks_still_defaults_to_no_embedding has a
misleading name that doesn't match its actual assertions. The test name suggests
it verifies that prepare_legal_chunks defaults embeddings to None, but the test
only asserts that main returns exit code 0. Either rename the test to accurately
reflect what it actually validates (such as testing that dry-run succeeds) or
add assertions that verify the no-embedding invariant by inspecting the output
or chunks to confirm embeddings are indeed not included.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend-ai/app/clients/supabase_client.py`:
- Around line 66-107: The SQL upsert query in the legal_document_chunks insert
operation unconditionally updates the updated_at timestamp whenever a
content_hash conflict occurs, even if the incoming chunk data is identical to
the existing row. This breaks idempotent reruns since repeated ingestion mutates
rows unnecessarily. Add a WHERE clause to the DO UPDATE section that only
performs the update when at least one of the actual data fields (such as law_id,
law_name, article_no, article_title, effective_date, source_name, source_url,
chunk_index, content, embedding, or metadata_json) has actually changed compared
to the existing row values, ensuring that updated_at is only advanced when the
data genuinely differs from what is already stored.

---

Nitpick comments:
In `@backend-ai/tests/test_legal_ingestion_upsert.py`:
- Around line 172-190: The test function
test_prepare_legal_chunks_still_defaults_to_no_embedding has a misleading name
that doesn't match its actual assertions. The test name suggests it verifies
that prepare_legal_chunks defaults embeddings to None, but the test only asserts
that main returns exit code 0. Either rename the test to accurately reflect what
it actually validates (such as testing that dry-run succeeds) or add assertions
that verify the no-embedding invariant by inspecting the output or chunks to
confirm embeddings are indeed not included.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ec0c3bcb-6c85-4af9-8a88-245c64659fd1

📥 Commits

Reviewing files that changed from the base of the PR and between 1231680 and 6941836.

📒 Files selected for processing (4)
  • backend-ai/app/clients/supabase_client.py
  • backend-ai/scripts/ingest_legal_docs.py
  • backend-ai/tests/test_legal_ingestion_upsert.py
  • phases/ai-legal-rag/phase5-legal-embedding-upsert.md

Comment thread backend-ai/app/clients/supabase_client.py
@HOKAGO-MEMORIES
HOKAGO-MEMORIES merged commit f504ee0 into develop Jun 22, 2026
1 check passed
@HOKAGO-MEMORIES
HOKAGO-MEMORIES deleted the phase/5-legal-embedding-upsert branch June 22, 2026 05:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Phase 5] legal embedding upsert

1 participant