Skip to content

Feat/pg vs neo4j benchmark#4

Open
withya16 wants to merge 11 commits into
mainfrom
feat/pg-vs-neo4j-benchmark
Open

Feat/pg vs neo4j benchmark#4
withya16 wants to merge 11 commits into
mainfrom
feat/pg-vs-neo4j-benchmark

Conversation

@withya16

Copy link
Copy Markdown
Contributor

pg_experiment: 전체 쿼리 원본 결과 + 진행 과정 문서 + 결론 보강

요약

이전 PR(#3)에서 다룬 latency 벤치마크에 이어, 다음을 추가한다.

  • 쿼리별 전체 원본 결과 덤프 (dump_full_results.py): 기존 verify_parity.py는 신원만, benchmark.py는 latency 숫자만 비교했어서 실제로 각 쿼리가 뭘 반환하는지는 기록이 없었음. 4개 쿼리를 고정 파라미터로 1회씩 실행해 Neo4j/Postgres 결과를 잘리지 않은 전체 행으로 남김.
  • 이 과정에서 발견된 이슈 3: ingredients_by_effects에도 path_by_effects와 같은 계열의 정렬 비결정성이 있었음 — RETINALHYDRATING/SOOTHING 두 효능에 완전히 동점(graph_score 동일)으로 걸려 있어 원본 Cypher의 정렬 키(ev_rank, graph_score)만으로는 어느 효능이 뽑힐지 결정되지 않음. SQL 포팅 버그가 아니라 프로덕션 쿼리 자체의 기존 특성.
  • RESULTS.md에 결론 섹션 추가: hop 수에 따라 유불리가 갈린다는 것 자체가 결론 — "관계가 명확하니 그래프DB가 맞다"도 "그러니 RDB로 갈아타면 된다"도 성급한 결론. 지금 프로덕션 쿼리 3개 기준으로는 1승은 Neo4j, 2승은 Postgres.
  • PROCESS.md 신규 추가: "이게 필요해서 이 쿼리를 날렸고 → 이런 결과가 나왔고 → 그래서 이렇게 판단했다" 흐름으로 실험 전체 과정을 시간순으로 서술.
  • 대화 중 나온 후속 질문 2건을 RESULTS.md §7(다루지 않은 것)에 기록: (1) 지금 4EVR0-Server는 LLM이 Cypher를 직접 생성하지 않고 고정 템플릿에 파라미터만 채운다는 걸 코드로 확인(recommend_service.py) → "Cypher가 LLM 친화적"이라는 그래프DB 장점은 지금 아키텍처에서 발동 안 함. (2) 그래프 구조가 추천 품질에 미치는 영향은 eval/RESULTS.md에 일부 다뤄졌으나 RDB 기준 재현 여부는 미확인.

구성

  • pg_experiment/dump_full_results.py (신규)
  • pg_experiment/results/full_query_dump.md (신규)
  • pg_experiment/PROCESS.md (신규)
  • pg_experiment/RESULTS.md (§3 전체 쿼리 결과, §2 이슈 3, §8 결론, §7 후속 과제 추가)

Test plan

  • dump_full_results.py 실행해 4개 쿼리 x 2엔진 결과 확인, RESULTS.md에 그대로 첨부

withya16 added 11 commits July 16, 2026 06:25
verify_parity.py/benchmark.py는 신원 또는 latency 숫자만 비교해서, 4개
쿼리가 실제로 뭘 반환하는지 잘리지 않은 전체 결과를 별도로 남김. 이 과정에서
ingredients_by_effects에도 동점 비결정성이 있는 걸 추가로 발견(RETINAL이
HYDRATING/SOOTHING에 동점으로 걸림).
- 4개 쿼리의 전체 원본 결과(파라미터 고정 1회 실행)를 요약 없이 그대로 첨부
- ingredients_by_effects의 동점 비결정성(발견된 이슈 3) 기록
- 벤치마크 결과를 종합한 결론 섹션 추가: hop 수에 따라 유불리가 갈리므로
  "그래프DB가 무조건 유리"도 "RDB로 충분"도 성급한 결론이라는 판단과 근거
PROCESS.md: "필요해서 이 쿼리를 날렸고 -> 이런 결과가 나왔고 -> 그래서
이렇게 판단했다" 흐름으로 실험 전체 과정을 시간 순으로 정리.

RESULTS.md §7에 후속 과제 추가:
- LLM이 쿼리를 직접 생성하는 구조가 아님을 코드로 확인
  (recommend_service.py는 고정 템플릿 호출, LLM은 파라미터 추출만 담당) ->
  "Cypher가 LLM 친화적"이라는 장점은 지금 아키텍처에서 발동하지 않음
- 그래프 구조가 추천 품질에 미치는 영향은 eval/RESULTS.md에 이미 일부
  다뤄졌으나 RDB 기준 재현 여부는 미확인
LLM_QUERY_GENERATION.md: 고정 템플릿(text-to-parameter) -> LLM이 매번
Cypher/SQL을 직접 생성하는 구조(text-to-query)로 바꾸려면 필요한 것들을
정리 - 아키텍처 변경, 가드레일(read-only 권한/LIMIT 강제/EXPLAIN 검증/
재시도 루프), 기존 pg_experiment 인프라를 재사용한 평가 방법.

§5로 추천 품질 비교(eval/RESULTS.md 방법론 재사용) + hop 분포 관찰
항목 추가: "자유도를 주면 hop이 늘어나서 그래프DB 우위가 더 명확해질
것"이라는 가설을 실제로 검증하려면 무엇을 같이 재야 하는지 정리.

DISCUSSION_quality_vs_hop.md: 위 가설이 나온 대화 원문 보존 (아직 실험
결과가 아니라 논의/가설 단계임을 분명히 하기 위해 별도 문서로 분리).
*.md 문서 5개(EXPERIMENT/RESULTS/PROCESS/LLM_QUERY_GENERATION/
DISCUSSION_quality_vs_hop)를 pg_experiment/docs/로 이동. 실행
스크립트(schema.sql, load_csv.py, queries.py, verify_parity.py,
benchmark.py, dump_full_results.py)와 결과 데이터(results/)는
pg_experiment/ 루트에 그대로 유지. 문서 간 상대 링크와
EXPERIMENT.md의 파일 트리 설명을 새 경로에 맞게 수정.
GraphDB/RDB x 고정/가변 쿼리 4칸을 정의하고, 이미 측정된 것(A vs C 속도 -
hop-의존적, A vs C 품질 - verify_parity.py로 델타 없음 확인됨)과 새로
측정해야 할 것(A vs B, C vs D, B vs D 품질 + B vs D, C vs D 속도)을 구분.

C vs D(RDB 안에서 고정 vs 가변)를 신규 비교 항목으로 추가해 4칸을 전부
커버하도록 확장. 결론을 미리 정하지 않고 6개 비교 결과를 실측 후 표로
채워서 종합 판단하는 프레임워크 제시 - A vs C 속도가 "일괄 승리"가 아니라
hop-의존적으로 나온 것처럼, 나머지도 그렇게 나올 가능성을 열어둠.
verify_parity.py/dump_full_results.py 재확인 결과 A vs C는 매칭 로직만
동일할 뿐 tie-break 비결정성 때문에 프로덕션 쿼리 3개 중 2개는 정확히
같은 결과가 아님 - "델타 없음"이라 단정했던 이전 서술을 정정. 다만 A는
이미 프로덕션 운영 중인 고정 기준선이라 A vs C 품질을 재도 앞으로의
선택(가변 전환 여부/엔진)에 영향이 없어 의사결정 프레임워크에서는
아예 빼기로 함 - 표를 6개에서 5개 비교로 축소.
C(RDB 고정)가 관여하는 비교(A vs C 품질, C vs D 전부)는 프로덕션 실제
선택지에 영향을 주지 않아 제외. B vs D도 속도는 별도로 재지 않기로 함 -
(1) hop 수만 알면 기존 A-C hop-scaling 곡선으로 속도 추정 가능,
(2) 가변 쿼리 시나리오의 진짜 병목은 실행 시간이 아니라 LLM 생성 시간이라
실행 시간 델타는 실질적 의미가 작음. 최종적으로 A vs B(가변 전환 가치)
-> B vs D(전환한다면 어느 엔진) 2단계 품질 비교로 정리.
DYNAMIC_QUERY_IMPLEMENTATION.md: LLM_QUERY_GENERATION.md의 "왜/무엇을
잴지"에 이어 "어떻게 코드로 짤지"를 정리. 기존 4EVR0-Server 패턴
(llm_client.py의 get_async_llm_client, app/prompts/의 load_prompt,
neo4j_client.py의 _log_query/예외 처리)을 그대로 재사용하는 방향으로
설계 - 새 파일(dynamic_query_client.py, dynamic_recommend_service.py,
프롬프트 2개)을 기존 고정 템플릿 경로와 분리해서 추가하고
settings.query_mode 플래그로 라우팅. 읽기 전용 DB 계정 분리, LIMIT
강제, EXPLAIN 검증, 재시도 루프, 생성 쿼리 텍스트 로깅, 오프라인 평가
-> 섀도 모드 -> 점진적 트래픽 전환 3단계 롤아웃까지 포함.
eval/gold_labels.py(concern->effect 정답 매핑)와
eval/graphrag_ranking_eval.py(Precision@K/NDCG@K 채점)가 이미 있어서
새로 안 만들어도 됨을 명시. A vs B를 먼저 실행하고(Cypher 생성
파이프라인만 필요), 결과가 긍정적일 때만 SQL 생성 파이프라인을 추가해
B vs D로 넘어가는 게이트형 실행 순서를 정리 - D 관련 작업을 조건부로
미뤄 불필요한 리소스 낭비를 막음.
AB_BD_EXECUTION_PLAN.md: 프로덕션 코드/가드레일/롤아웃(그건
DYNAMIC_QUERY_IMPLEMENTATION.md)과 무관하게, 오프라인 실험을 실제로
어떻게 돌릴지만 다룸 - 재사용할 기존 인프라(eval/gold_labels.py,
eval/graphrag_ranking_eval.py), 신규 스크립트 목록/위치
(pg_experiment/llm_eval/questions.py, generate.py, run_ab.py, run_bd.py),
게이트형 실행 순서.

LLM_QUERY_GENERATION.md §7은 새 문서로의 포인터로 축소해 중복 제거.
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.

1 participant