Phase G: Kei API 통신 정상화 — streaming 전환 + Sonnet fallback 제거

G-1: httpx non-streaming → streaming 전환 (3개 파일)
  - client.post() → client.stream("POST") + response.aiter_lines()
  - SSE 토큰을 실시간 수신 (30분+ 무응답 해소)

G-2: Sonnet fallback 완전 제거
  - kei_client.py: classify_content()에서 _call_anthropic_direct() 호출 제거
  - content_editor.py: fill_content()에서 Sonnet fallback 분기 제거
  - Kei API만 사용. 실패 시 manual_classify() 또는 _apply_defaults() 안전망

G-3: _parse_json() 마크다운 제거 3파일 동기화
  - content_editor.py, design_director.py에 kei_client.py와 동일한 전처리 추가

G-4: FAISS를 CPU로 전환 (GPU 메모리 경쟁 해소)
  - block_search.py + build_block_index.py: device="cpu"

G-5: streaming 파서에 event:error 처리
  - persona_agent 에러 시 무한 대기 방지. 즉시 중단.

G-6: content_editor.py None 가드
  - Kei API 실패 시 _parse_json(None) TypeError 방지

G-7: "mode" → "mode_hint" 필드명 수정 (3개 파일)
  - persona_agent의 실제 필드명에 맞춤

persona_agent 수정: 0건

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-26 01:26:03 +09:00
parent 7038418c8b
commit a01f7a7f8a
8 changed files with 519 additions and 152 deletions

View File

@@ -73,7 +73,7 @@ def build_search_texts(blocks: list[dict]) -> list[str]:
def build_index(texts: list[str]) -> tuple[faiss.IndexFlatIP, np.ndarray]:
"""텍스트를 임베딩하고 FAISS 인덱스를 생성한다."""
logger.info(f"임베딩 모델 로딩: {EMBEDDING_MODEL}")
model = SentenceTransformer(EMBEDDING_MODEL)
model = SentenceTransformer(EMBEDDING_MODEL, device="cpu")
logger.info(f"{len(texts)}개 텍스트 임베딩 중...")
embeddings = model.encode(
@@ -145,7 +145,7 @@ def main():
logger.info(f"✅ 검증 통과: {test_index.ntotal}개 벡터, {len(test_meta)}개 메타데이터")
# 6. 테스트 검색
model = SentenceTransformer(EMBEDDING_MODEL)
model = SentenceTransformer(EMBEDDING_MODEL, device="cpu")
test_queries = [
"A vs B 두 개념 비교",
"연도별 정책 로드맵",