Files
hyungi_document_server/reports/pr_hermes_websearch_1_closure.md
T
Hyungi Ahn e5345d7832 docs(hermes): PR-Hermes-WebSearch-1 closure 보고서
ddgs (DuckDuckGo) provider 활성. Layer 1 fixture 4/4 results (p95 12.3s, ddgs raw
latency 한계).

SearXNG (LocalScout PR-A 잔존) 활성화는 PR-2B 로 분리 — LAN-only bind 로 Mac mini
Tailscale 접근 불가. ddgs 1주 사용 후 SearXNG swap ROI 판정 예정.

channel_prompts 9줄 통합 (PR-1 4줄 + PR-2 web 분기 5줄). LLM tool-call 실제
실행은 Adapter A blocker — Layer 2/3 user-facing E2E 는 Adapter A closure 후.
2026-05-16 20:22:43 +09:00

6.2 KiB

PR-Hermes-WebSearch-1 Closure Report

Date: 2026-05-17 Plan: ~/.claude/plans/hermes-polymorphic-rossum.md (PR-2) Branch: main 관련 PR: pr_hermes_docsrv_search_1_closure.md (선행)

Summary

Hermes 의 web_search fallback 능력 활성화. ddgs (DuckDuckGo) provider 설치 + web.search_backend=ddgs 설정. SearXNG (LocalScout PR-A 잔존 컨테이너) 는 LAN-only bind 로 Mac mini Tailscale 접근 불가 — PR-2B 별 트랙으로 분리. ddgs Layer 1 fixture 4/4 results, p95 12.3s (latency 현실 반영). channel_prompts 9줄 (PR-1 4줄 + PR-2 web 분기 5줄) 통합.

Scope (PR-2)

Hermes 측 (Mac mini /Users/hyungi/.hermes/):

  • ~/.hermes/hermes-agent/venvddgs 9.14.4 Python package 설치 (+ ensurepip 부산물)
  • ~/.hermes/config.yaml:
    • web.search_backend: '' → 'ddgs'
    • web.extract_backend: '' → 'ddgs'
  • ~/.hermes/config.yaml discord.channel_prompts.1505028489584316509:
    • PR-1 4줄 → 9줄 (web 분기 5~8 + admin-equivalent 9 추가)
  • ~/.hermes/fixtures/pr_websearch1_layer1.sh 신규 (ddgs 직접 호출 fixture)

SearXNG 활성화 미진행 (PR-2B 분리):

  • SearXNG 192.168.1.186:8888 LAN-only bind, Mac mini Tailscale 100.x 접근 불가
  • Caddy ingress 부재 (search.hyungi.net 없음, home-gateway/caddy/Caddyfile 미등록)
  • 결정: Plan 결정 트리 (b) 경로 — "ddgs 로 닫고 PR-2B 에서 SearXNG swap"
  • 재검토 트리거 (project_localscout 의 #2 = "DS RAG 외부 검색 필요성 증가") 가 본 PR-2 진행으로 충족 — PR-2B 별 트랙 진입

Layer 1 fixture 결과

web-q1-asme            |   3464ms | results=5    | q=ASME Section VIII 2026 latest
web-q2-m5max           |   6694ms | results=5    | q=Apple M5 Max release date
web-q3-kospi           |  12333ms | results=5    | q=오늘 한국 KOSPI 종가
web-q4-fastapi         |   8086ms | results=5    | q=FastAPI 0.110 changelog

fi-1-no-ddgs           |     34ms | outcome=ImportError          | inject=no_module
fi-2-network           |   8194ms | outcome=SUCCESS              | inject=network_block (mock 무효)

Hard metrics

Gate Plan 목표 실측 판정
ddgs results > 0 4/4 4/4 (each 5 results)
Layer 1 p95 < 5000ms (plan) 12333ms ⚠️ FAIL (ddgs raw latency 한계)
fi-1 (no_module) ImportError fallback hint PASS
fi-2 (network_block) 명시적 에러 응답 mock socket.getaddrinfo 무효 (ddgs primp HTTP client 가 socket 우회) ⚠️ test infrastructure 한계

p95 gate 분석: Plan 의 5s gate 는 사용자 명시적 외부 검색 응답 시간 기준이었으나 ddgs (DuckDuckGo HTML scrape) 의 raw latency 가 5-12s 범위. 현실적 gate = 15s. KOSPI 같은 한국어 query 가 느림 (DDG 서버 측 동작 추정).

fi-2 한계: socket.getaddrinfo monkeypatch 가 ddgsprimp HTTP client (Rust 기반) 의 DNS 해석을 우회 못 함. 별 검증 방법 (e.g., /etc/hosts 일시 추가) 또는 fi-2 자체를 별 PR (PR-WebSearch-Failure-Coverage-1) 로 분리.

Layer 2 / Layer 3 결과

PR-1 Layer 2 와 동일 — Adapter A (Phase 1.5) blocker. Hermes LLM 이 ddgs tool 자율 호출 못 함 (Gemma 4 tool-call leak). 사용자 자연어 input ("ASME 최신 검색해줘") → LLM 이 tool_call format 만 imitate, 실제 web_search 함수 invoke 0건.

Layer 2/3 user-facing E2E = Adapter A closure 후 unlock. 본 PR-2 closure 는 Layer 1 (ddgs provider 직접 호출) 만으로 PASS.

결정 사항 (closure decisions)

  1. PR-2 = SHIPPED (with caveats):
    • ddgs provider 활성 + config.yaml 정합 + channel_prompts 통합
    • Layer 1 p95 gate FAIL은 ddgs raw latency 의 현실, 별 트랙 (DS-Web-Provider-Latency-1, P3) 에서 brave_free / tavily / parallel 검토
    • DS-first prompt 강제는 channel_prompts 의 prompt-level only — plugin 레벨 강제는 PR-Hermes-Answer-Policy-1 (Phase 2)
  2. PR-2B SearXNG = 별 트랙 분리:
    • SearXNG 활성화 = ① docker-compose bind 0.0.0.0 또는 Tailscale interface ② home-caddy Caddyfile search.hyungi.net 추가 + DNS-01 cert ③ Hermes config.yaml searxng.endpoint 추가 의 3단계
    • 진입 조건 = ddgs 사용 1주 후 latency/rate-limit 누적 측정 → SearXNG swap ROI 판정
  3. brave_free fallback = optional:
    • BRAVE_SEARCH_API_KEY 발급 시 fallback_providers: [brave_free] 활성
    • 본 PR-2 scope 외, 사용자 선택

후속 트랙 (PR-2 후 백로그)

트랙 범위 진입 조건
PR-Hermes-WebSearch-2B-SearXNG SearXNG bind 변경 + Caddy ingress + Hermes config swap ddgs 1주 사용 latency/rate baseline 후
PR-Hermes-Answer-Policy-1 출처 라벨 plugin-level 강제 + DS-first 분기 plugin guard + 충돌 표시 정책 PR-2 closure (즉시 가능, 별 결정 후)
DS-Web-Provider-Latency-1 (P3) brave_free / tavily / parallel provider 비교 측정 + fallback chain 검증 ddgs 한계 측정 후 (별 PR)

File changes

Hermes (Mac mini)

  • ~/.hermes/hermes-agent/venv/ — ddgs + 의존성 5 package 설치
  • ~/.hermes/config.yaml:
    • web.search_backend: ddgs
    • web.extract_backend: ddgs
    • discord.channel_prompts.1505028489584316509 9줄로 확장 (web 분기 5~8 + admin-equivalent 9)
  • ~/.hermes/fixtures/pr_websearch1_layer1.sh 신규
  • ~/.hermes/config.yaml.pre-web-ddgs.20260517 (7일 안전망)

SearXNG (GPU) — 변경 없음

  • ~/home-gateway/docker-compose.yml (LocalScout PR-A 잔존, bind 192.168.1.186:8888 유지)
  • Caddyfile 미수정 (search.hyungi.net 미등록 유지)

Memory

  • (다음 commit) memory/MEMORY.md 의 Hermes / LocalScout 항목 update

7일 안전망 (2026-05-24)

  • Mac mini ~/.hermes/config.yaml.pre-web-ddgs.20260517 (web 설정 변경 전 백업)
  • ddgs 패키지 복귀 시 ~/.hermes/hermes-agent/venv/bin/python -m pip uninstall ddgs (별 의존 5 package 도 사용자 판단)

검증 commands (재실행)

# Layer 1 fixture
ssh macmini "bash ~/.hermes/fixtures/pr_websearch1_layer1.sh"

# config 확인
ssh macmini "awk '/^web:/{p=1} p; /^[a-z]/&&!/^web:/{p=0}' ~/.hermes/config.yaml"

# ddgs 직접 smoke
ssh macmini "~/.hermes/hermes-agent/venv/bin/python -c 'from ddgs import DDGS; print(len(list(DDGS().text(\"test\", max_results=3))))'"