<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Spacy on ICE-ICE-BEAR-BLOG</title><link>https://ice-ice-bear.github.io/ko/tags/spacy/</link><description>Recent content in Spacy on ICE-ICE-BEAR-BLOG</description><generator>Hugo -- gohugo.io</generator><language>ko</language><lastBuildDate>Wed, 22 Apr 2026 00:00:00 +0900</lastBuildDate><atom:link href="https://ice-ice-bear.github.io/ko/tags/spacy/index.xml" rel="self" type="application/rss+xml"/><item><title>hybrid-image-search-demo 개발 로그 #17 — HEX 전용 주입, 앵글 카테고리 분할, 한국어 프롬프트 추출</title><link>https://ice-ice-bear.github.io/ko/posts/2026-04-22-hybrid-search-dev17/</link><pubDate>Wed, 22 Apr 2026 00:00:00 +0900</pubDate><guid>https://ice-ice-bear.github.io/ko/posts/2026-04-22-hybrid-search-dev17/</guid><description>&lt;img src="https://ice-ice-bear.github.io/" alt="Featured image of post hybrid-image-search-demo 개발 로그 #17 — HEX 전용 주입, 앵글 카테고리 분할, 한국어 프롬프트 추출" /&gt;&lt;h2 id="개요"&gt;개요
&lt;/h2&gt;&lt;p&gt;16개 커밋, 세 갈래. 새 &lt;strong&gt;HEX 전용 주입 모드&lt;/strong&gt;(톤 이미지는 빼고, 헥스 팔레트만 프롬프트에 주입), &lt;strong&gt;앵글 피커를 3-카테고리로 분할&lt;/strong&gt;한 인라인 UI, 그리고 &amp;ldquo;하늘을 달리는 남자&amp;rdquo; 프롬프트에 여성 모델이 붙던 프로덕션 회귀를 잡는 &lt;strong&gt;한국어 프롬프트 속성 추출기&lt;/strong&gt;. 작은 OTLP 튜닝(스팬 배치, 메트릭 간격 확대)이 뒷마무리.&lt;/p&gt;
&lt;p&gt;이전 글: &lt;a class="link" href="https://ice-ice-bear.github.io/posts/2026-04-17-hybrid-search-dev16/" &gt;hybrid-image-search-demo 개발 로그 #16&lt;/a&gt;&lt;/p&gt;
&lt;pre class="mermaid" style="visibility:hidden"&gt;graph LR
 U["사용자 프롬프트 (KO)"] --&gt; Extract["속성 추출기&amp;lt;br/&amp;gt;spaCy + few-shot LLM"]
 Extract --&gt; Gender["gender"]
 Extract --&gt; Age["age"]
 Extract --&gt; Race["race"]
 Gender --&gt; Model["모델 이미지 주입"]
 Age --&gt; Model
 Race --&gt; Model
 U --&gt; Inject{주입 모드}
 Inject --&gt;|off| P0["원본 프롬프트"]
 Inject --&gt;|auto| PT["톤 이미지 + 헥스"]
 Inject --&gt;|hex_only| PH["헥스 팔레트만"]
 Model --&gt; Prompt["최종 프롬프트"]
 P0 --&gt; Prompt
 PT --&gt; Prompt
 PH --&gt; Prompt&lt;/pre&gt;&lt;h2 id="hex-전용-주입-모드"&gt;HEX 전용 주입 모드
&lt;/h2&gt;&lt;p&gt;톤 주입 시스템의 두 축: &lt;strong&gt;톤 레퍼런스 이미지&lt;/strong&gt;(3장 또는 5장, 헥스 색으로 추출)와 &lt;strong&gt;프롬프트 조각&lt;/strong&gt;(이미지를 생성 프롬프트 안에서 프레이밍). 기존 기본값은 두 가지를 함께 — 이미지도 주입하고 톤 방향성 텍스트도 넣는다. 이번 세션의 요청은 세 번째 모드, 즉 헥스 팔레트만 색상 가이드로 들어가고 톤 이미지 경로는 완전히 건너뛰는 것.&lt;/p&gt;
&lt;p&gt;설계(&lt;code&gt;44d5bff&lt;/code&gt;, &lt;code&gt;08916cb&lt;/code&gt;)는 이를 3-way &lt;code&gt;injection_mode&lt;/code&gt; 열거형으로 통합했다: &lt;code&gt;off&lt;/code&gt; / &lt;code&gt;auto&lt;/code&gt; / &lt;code&gt;hex_only&lt;/code&gt;. 배선 작업이 대부분이었다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;refactor(prompt)&lt;/code&gt;: &lt;code&gt;hex_colors&lt;/code&gt;를 명시적 파라미터로 승격, 헥스 전용 프롬프트 블록 추가(&lt;code&gt;0a16f4f&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;feat(db)&lt;/code&gt;: &lt;code&gt;log_generation&lt;/code&gt;과 하이드레이션에 &lt;code&gt;injection_mode&lt;/code&gt; 실기(&lt;code&gt;e53be41&lt;/code&gt;) — 생성 레코드가 나중에 디버깅 시 모드를 재구성할 수 있어야 하므로 필요.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;feat(backend)&lt;/code&gt;: &lt;code&gt;injection_mode&lt;/code&gt;를 end-to-end로 off/auto/hex_only 배선(&lt;code&gt;e6807e2&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Alembic 마이그레이션 &lt;code&gt;20260420_add_injection_mode.py&lt;/code&gt;로 컬럼 추가.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;feat(ui)&lt;/code&gt;: 각 모드를 설명하는 a11y 툴팁이 달린 3-way 토글 필(&lt;code&gt;5659fd3&lt;/code&gt;, &lt;code&gt;3b2cf22&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;UI 폴리시(&lt;code&gt;51464e6&lt;/code&gt;)는 몇 번 돌았다. 초기 디자인은 비활성 상태가 중립 회색이었는데, &amp;ldquo;off&amp;quot;가 &lt;strong&gt;비활성&lt;/strong&gt;으로 읽히지 않았다 — 사용자들이 여전히 활성 상태라고 오해했다. 픽스: 비활성 필은 빨강, 활성 필은 노랑. 대비가 강해지고, 상태를 한 번에 읽을 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;fix(ui)&lt;/code&gt; 커밋(&lt;code&gt;988ea37&lt;/code&gt;)은 &lt;code&gt;hex_only&lt;/code&gt; 모드에서도 톤 방향성 텍스트를 여전히 보여주던 프롬프트-표시 헬퍼를 덮었다 — 남아 있던 복사 경로. &lt;code&gt;chore(gen)&lt;/code&gt;(&lt;code&gt;c419349&lt;/code&gt;)은 세 모드가 Grafana 스팬에 또렷하게 뜨도록 텔레메트리 라벨을 정돈했다.&lt;/p&gt;
&lt;h2 id="앵글-피커-3-카테고리-인라인-ui"&gt;앵글 피커: 3-카테고리 인라인 UI
&lt;/h2&gt;&lt;p&gt;커밋 &lt;code&gt;61c5802&lt;/code&gt;는 앵글 셀렉션을 플랫 리스트에서 3-카테고리 인라인 UI로 분할한다(#16에서 정리한 렌즈 피커 패턴으로 미루어 &amp;ldquo;general / beauty / product&amp;rdquo; 같은 구성일 것). 구조적 동기는 2회차 전 렌즈 피커 확장과 동일 — 5개가 넘는 플랫 리스트는 노이즈가 되고, 그룹화가 스캐너빌리티를 복구한다.&lt;/p&gt;
&lt;p&gt;세련된 프론트엔드 이슈는 3-카테고리 분할에 결정적 표시 순서가 필요하다는 것 — 백엔드 &lt;code&gt;angle_registry&lt;/code&gt;의 반영도와 JSON 스키마의 카테고리 메타데이터로 해결. 컴포넌트는 스키마를 한 번 읽고 섹션으로 렌더하며, 셀렉션은 여전히 단일 &lt;code&gt;angle_id&lt;/code&gt;를 백엔드에 emit — API 표면은 변하지 않는다.&lt;/p&gt;
&lt;h2 id="한국어-프롬프트-속성-추출"&gt;한국어 프롬프트 속성 추출
&lt;/h2&gt;&lt;p&gt;이 갈래를 시작하게 만든 프로덕션 버그: 프롬프트 &amp;ldquo;하늘을 달리는 남자&amp;quot;가 &lt;code&gt;Araya 05.png&lt;/code&gt;(&lt;code&gt;data/model_labels.json&lt;/code&gt;에서 여성으로 라벨됨)를 모델 레퍼런스로 붙여 생성했다. LLM 기반 속성 추출기가 성별을 잘못 고른 것.&lt;/p&gt;
&lt;p&gt;픽스(&lt;code&gt;61e6c85&lt;/code&gt;)는 &lt;strong&gt;few-shot 프롬프트&lt;/strong&gt;로 성별/나이/인종 추출을 예시와 함께 강제한다. 분류기를 따로 돌리기보다 프롬프트 스키마를 조이는 쪽이 단순하다 — 세션 중의 결정은 마이너 가드레일로 충분하다는 것이었다. 한국어 프롬프트 입력 공간은 넓고, 제대로 된 분류기는 라벨된 코퍼스가 필요하니까.&lt;/p&gt;
&lt;p&gt;spaCy 핀(&lt;code&gt;9f2773b&lt;/code&gt;)도 연관. &lt;code&gt;en_core_web_sm&lt;/code&gt;이 새 venv에서 자동 업그레이드되고 있었고, 프롬프트 파서는 특정 토큰 타입에 의존한다. 핀을 박아서 파싱을 재현 가능하게 만들었다.&lt;/p&gt;
&lt;h2 id="otlp-텔레메트리-튜닝"&gt;OTLP 텔레메트리 튜닝
&lt;/h2&gt;&lt;p&gt;두 개의 작지만 하중 있는 변경(&lt;code&gt;02c0c6c&lt;/code&gt;): &lt;strong&gt;스팬 배치&lt;/strong&gt;(per-span 대신) — 실제 트래픽에서는 반드시 덮어야 하는 OpenTelemetry 기본값 중 하나. 그리고 &lt;strong&gt;메트릭 간격 확대&lt;/strong&gt; — Grafana Cloud 무료 플랜 수용량 안에 안정적으로 들어가도록. 트라이얼이 끝났으니 대시보드는 무료에 맞춰야 한다.&lt;/p&gt;
&lt;h2 id="커밋-로그"&gt;커밋 로그
&lt;/h2&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;메시지&lt;/th&gt;
 &lt;th&gt;변경&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;docs(spec): HEX-only tone injection mode design&lt;/td&gt;
 &lt;td&gt;설계&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;docs(plan): HEX-only tone injection implementation plan&lt;/td&gt;
 &lt;td&gt;계획&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;refactor(prompt): promote hex_colors to explicit param, add hex-only block&lt;/td&gt;
 &lt;td&gt;프롬프트 빌더&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;feat(angle): split angle selection into 3 categories with inline UI&lt;/td&gt;
 &lt;td&gt;앵글 피커&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;chore(deps): pin en_core_web_sm so venv rebuilds include spaCy model&lt;/td&gt;
 &lt;td&gt;재현성&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;feat(db): thread injection_mode through log_generation and hydration&lt;/td&gt;
 &lt;td&gt;DB + ORM&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;feat(backend): wire injection_mode end-to-end (off/auto/hex_only)&lt;/td&gt;
 &lt;td&gt;백엔드 배선&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;fix(deploy): restart backend and frontend via pm2&lt;/td&gt;
 &lt;td&gt;배포 핫픽스&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;feat(ui): 3-way injection mode toggle (off/auto/hex_only)&lt;/td&gt;
 &lt;td&gt;UI&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;chore(ui): polish injection mode pill a11y and tooltips&lt;/td&gt;
 &lt;td&gt;a11y&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;fix(ui): respect hex_only mode in prompt-display helpers&lt;/td&gt;
 &lt;td&gt;UI 동기&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;style(ui): make all inactive injection pills red for stronger active signal&lt;/td&gt;
 &lt;td&gt;비주얼 대비&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;fix(generation): extract gender/age/race reliably from Korean prompts&lt;/td&gt;
 &lt;td&gt;파서 픽스&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;fix(telemetry): batch spans and widen metric interval&lt;/td&gt;
 &lt;td&gt;OTLP 튜닝&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="인사이트"&gt;인사이트
&lt;/h2&gt;&lt;p&gt;두 갈래가 같은 교훈을 공유한다: &lt;strong&gt;명시적 모드가 암묵적 폴백을 이긴다.&lt;/strong&gt; &lt;code&gt;injection_mode&lt;/code&gt; 열거형은 &amp;ldquo;플래그 기본값이 두 가지를 동시에 건드리는&amp;rdquo; 기존 설계보다 순전히 낫다 — 각 코드 경로가 호출 지점에서 읽힌다. 여덟 개 불리언을 추적하지 않아도 된다. 한국어 프롬프트 추출기도 같은 결. 예전에는 LLM의 기본 동작에 의존했는데, &lt;strong&gt;대부분&lt;/strong&gt; 되다가 어느 순간 안 된다. few-shot 프롬프트도 여전히 LLM 기반이지만 이제 결정이 프롬프트 자체에 가시화된다. 비주얼 대비도 같은 원리 — &amp;ldquo;off&amp;rdquo; 토글이 중립으로 보이는 순간 사용자는 off로 읽기를 멈춘다. 다음 세션의 초점: 세션 4에서 나온 자동채움 토큰 확장 — 3장이나 5장을 한 번에 편집하는 UI가 필요.&lt;/p&gt;</description></item></channel></rss>