[FEAT#149] LLM 자동 parsing rule 생성 wiring (1차: cmd + llmgen + parser_worker fallback) - #168
Conversation
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (7)
📝 WalkthroughWalkthroughThis PR implements an LLM-driven automatic rule generator that generates CSS selectors for unsupported websites when the parser encounters Changes
Sequence DiagramsequenceDiagram
participant ParserWorker
participant Generator
participant InflightSet
participant LLMProvider
participant HTML Parser
participant Repository
participant Resolver
ParserWorker->>ParserWorker: handleRuleError (ErrNoRule detected)
ParserWorker->>Generator: Enqueue(ctx, host, targetType, rawContent)
Generator->>InflightSet: tryAcquire(host, targetType)
alt Already in-flight
InflightSet-->>Generator: false
Generator-->>ParserWorker: return (dedup skipped)
else Not in-flight
InflightSet-->>Generator: true
Generator->>Generator: spawn background goroutine<br/>(context.WithoutCancel)
Generator-->>ParserWorker: return (async)
Generator->>Generator: BuildPrompt(host, targetType, html)
Generator->>LLMProvider: Generate(prompt, taskHint="json")
LLMProvider-->>Generator: response
Generator->>Generator: extractJSON(response)
Generator->>Generator: parseSelectorMap(jsonStr)
Generator->>HTML Parser: Parse HTML with goquery
Generator->>Generator: validateSelectors(selectorMap, parsed HTML)
alt Validation succeeds
Generator->>Repository: Insert(disabled ParsingRuleRecord)
Repository-->>Generator: ok
Generator->>Resolver: Invalidate(host, targetType)
Resolver-->>Generator: ok
else Validation fails
Generator->>Generator: log error
end
Generator->>InflightSet: release(host, targetType)
InflightSet-->>Generator: ok
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related issues
Possibly related PRs
Suggested labels
Poem
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Review rate limit: 0/1 reviews remaining, refill in 60 minutes.Comment |
There was a problem hiding this comment.
Code Review
This pull request introduces an LLM-powered parsing rule generator that automatically creates selectors for hosts lacking registered rules. The implementation includes an in-process deduplication set, prompt construction logic, and integration into the parser worker. The review feedback highlights several improvement opportunities: preserving observability metadata in background tasks by using context.WithoutCancel, implementing a graceful shutdown mechanism for asynchronous generation tasks, and removing redundant code.
…(이슈 #149) - LLM_ENABLED / LLM_PROVIDER / LLM_MODEL / LLM_TIMEOUT 지원 - API key 는 GEMINI_API_KEY / OPENAI_API_KEY / ANTHROPIC_API_KEY 자동 조회 + LLM_API_KEY fallback - default: enabled=true, provider="gemini", model="gemini-2.5-flash", timeout=60s
- prompt.go: target_type 별 system/user 프롬프트 + JSON 추출 (markdown 펜스 무시) - generator.go: Enqueue (비동기) → LLM 호출 → SelectorMap 파싱 → goquery validation → INSERT (enabled=false) → Resolver.Invalidate - dedup.go: in-process inflightSet — 동일 (host, type) 동시 호출 1회로 제한 - 본 PR 은 enabled=false 로 INSERT — 운영자 spot-check 후 enable=true flip - source_name="llm-auto" 로 hand-tuned rule 과 구분 - 단위 테스트 7건: 페이지/리스트 성공, validation 실패 reject, LLM 에러 reject, in-flight dedup, 다중 host, 빈 HTML skip
- ParserWorker 에 llmGen *llmgen.Generator 필드 (nil 허용 — 비활성 시 graceful degrade) - handleRuleError 시그니처에 raw + storage.TargetType 추가 - rule.ErrNoRule + llmGen 활성화 → Enqueue 로 비동기 generation 트리거 + raw 잔존 + commit - 다른 rule.Error (parse_failure / empty_selector) 는 기존 동작 유지 (운영자 review)
#149) - pkg/llm/providers blank-import 으로 gemini/openai/anthropic 자동 등록 - buildLLMGenerator: LoadLLM → llm.New → policy.NewFixedOrder(provider) → chain.NewWithPolicy → llmgen.New - LLM_ENABLED=false / API key 누락 / provider 생성 실패 시 nil 반환 (graceful degrade) - 본 PR scope: FixedOrder("gemini") 단일 provider — 후속 PR 에서 chain (gemini→openai→anthropic) 으로 확장 - ParserWorker 생성자에 llmGen 주입
…emini) - Generator 에 sync.WaitGroup + atomic.Bool stopped + Stop(ctx) 메소드 추가 - 진행 중 background goroutine 의 완료 대기 (셧다운 보장) - Stop 후 Enqueue 는 noop — 새 작업 차단 - Stop 은 idempotent (CompareAndSwap) - Enqueue: context.Background() → context.WithoutCancel(ctx) — trace ID / logger 메타데이터 보존 - runOnce 에서 logger.FromContext(bgCtx) 로 호출자 child logger 우선 사용 - main.go shutdown sequence 에 llmGen.Stop 추가 (parser worker 정지 후 호출 — enqueue source 차단 보장) - 테스트 4건 추가: in-flight 대기 / Stop 후 noop / Stop idempotent / 호출자 ctx cancel 무관 진행
…149/llm-rule-generator-wiring
연관 이슈
구현 내용
이슈 #149 의 1차 PR 입니다 — Section 1 + 2 + 3 + 기본 validation + 단위 테스트 범위.
1. LLM provider 와이어링 (
cmd/issuetracker/main.go)pkg/llm/providersblank-import 으로 gemini/openai/anthropic 자동 등록buildLLMGenerator헬퍼:LoadLLM → llm.New → policy.NewFixedOrder → chain.NewWithPolicy → llmgen.NewLLM_ENABLED=false/ API key 누락 / provider 생성 실패 시 nil 반환 (graceful degrade — 기존 host 정상 파싱 유지)2. LLM rule generator 컴포넌트 (
internal/crawler/parser/rule/llmgen/)prompt.go: target_type 별 프롬프트 + JSON 추출 (markdown 펜스 무시, brace balancing)generator.go: 비동기 Enqueue → LLM 호출 → SelectorMap 파싱 → goquery validation → INSERT (enabled=false) →Resolver.Invalidatededup.go: in-processinflightSet— 동일 (host, type) 동시 호출 1회로 제한source_name="llm-auto"+enabled=false(운영자 spot-check 게이트)3. ErrNoRule fallback 진입점 (
internal/parser/worker/parser_worker.go)ParserWorker.llmGen필드 추가 (nil 허용)handleRuleError시그니처에 raw + storage.TargetType 추가rule.ErrNoRule + llmGen 활성화→ 비동기 enqueue + raw 잔존 + commitrule.Error(parse_failure / empty_selector) 는 기존 동작 유지4. 기본 validation (안전망 일부)
goquery.Find().Length() > 0검증5. 단위 테스트 (race 검증 포함)
현재
policy.NewFixedOrder("gemini")단일 provider 만 사용 — 1000회/일 무료 한도 내 검증 목적.운영 배포 전에 chain (gemini → openai → anthropic) 으로 확장해야 함 — 후속 이슈에서 추적.
CI / 머지 게이트 점검
변경 영향 범위
pkg/config(LLMConfig + LoadLLM 추가)internal/crawler/parser/rule/llmgen(신규)internal/parser/worker(handleRuleError 시그니처)cmd/issuetracker(LLM provider 와이어링)Required Status Checks
Commit LintPR Title LintLinked Issue CheckFormat CheckBuildTestLint롤백 계획
LLM_ENABLED=false설정 → 즉시 비활성 (배포 재기동만 필요)source_name="llm-auto"로 식별 가능 — 필요 시DELETE FROM parsing_rules WHERE source_name='llm-auto'로 정리TODO (후속 이슈로 추적)
FixedOrder("gemini")→Hybrid또는 명시 chain (gemini → openai → anthropic)논의 사항
background ctx사용 — parser worker 의 message commit 과 LLM generation 의 lifecycle 을 분리. 논의 여지 있음enabled=false정책: 운영자 review 게이트. 자동 enable 정책은 후속 이슈에서 검토 (validation 강도와 연동)Summary by CodeRabbit
Release Notes