
    ֓ǰ                       d Z ddlmZ ddlZddlZddlZddlmZmZm	Z	m
Z
mZ ddlmZmZmZmZ  ej"                  e      ZdZdZdZd	Zd
Z	 	 	 	 d%dZdZefd&dZd'dZdded	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d(dZef	 	 	 d)dZdddedd	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d*dZdZ d+dZ!d,dZ"dd	 	 	 	 	 	 	 	 	 d-dZ#dZ$d.dZ%ddd	 	 	 	 	 	 	 	 	 	 	 d/dZ&d Z'd!Z(d"Z)	 	 	 	 d0d#Z*d1d$Z+y)2u	  유형 사전지식 그라운딩(실험) — 결손 문항 → 원본어 검색 → 일치 채택.

## 왜 이 단계가 필요한가 (2026-07-31 실측)

씨드 저작은 **시나리오 원문 + place spec** 두 가지만 근거로 쓴다. 그래서
둘 다 침묵한 항목은 이미지 모델이 임의로 정한다. `bg_multifamily_residence`
실측 — 외부 계단이 **무엇에 닿는지**가 어느 층에도 없었다:

    시나리오  "한 다세대 주택 외부 계단을 다급히 올라간다"   → 도착점 없음
    place spec "rises ... toward its access point"           → 자기참조
    브리프     "reaches the alley-side access point"          → 승계
    생성 프롬프트 "rises along the outside wall to the access landing"

"출입점으로 올라간다"는 동어반복이라 층이 비어 있고, 모델이 2층 문에
임의로 붙였다. 사용자 육안 반려("옥상으로 올라가는 계단이 아니야").

팩 v11 은 이미 "목록에 없다 = 없다가 아니다, 유형 통상에 위임하라"를
명문화했다. 이 모듈은 그 **'통상'을 모델 기억 대신 검색 사실로** 바꾼다.

## 계약

0. **대상 = 당연하지 않은 것만** (v3, 2026-08-03). 그 유형이면 늘 있는 것은
   묻지 않는다 — 그림 모델이 이미 알고, 물으면 하나뿐인 질의를 차지해
   정작 필요한 것을 묻는다. 남는 것은 보통 하나. 무엇이 특별한지는 명세가
   붙인 **이름이 아니라 원문 인용**을 보고 LLM 이 정한다.
1. **권위 = 결손 전용.** 시나리오 > place spec > 유형 사전지식.
   침묵한 항목에서만 쓰고, 충돌하면 시나리오·spec 이 이긴다.
2. **문항·질의는 유형 일반으로 환원.** 작품 고유명사·인물·사건·배치를
   넣지 않는다 — `search_grounded_ref` 의 기존 검색 계약과 동형
   ("must not contribute people, events, temporary objects, layout, or
   any story-specific name").
3. **이중 검색 후 일치만 채택.** 두 실행이 같은 사실을 말할 때만 쓴다.
   불일치·미발견은 폐기 — 채택하지 않아도 팩 v11 의 전형 위임으로
   되돌아갈 뿐이라 손해가 없다(fail-closed).
4. **질의 언어는 시나리오 원문어.** 영어로 물으면 그 지역의 전형이
   아니라 영어권 전형이 돌아온다(기존 계보 실측).

## 격리

순수 함수 + 호출만 담는다. DB 쓰기·체크포인트·스텝 오케스트레이션 없음.
    )annotationsN)AnyDictListOptionalSequence)SearchNotPerformedbuild_web_search_toolresponse_reasoning_effortweb_search_call_counts4   )gpt-6-astrar   gptz
gemini-proc                L    t        |xs i       }|j                  | d|i       |S )u  모델 분업을 명시 배선한다.

    이 모듈의 step 이름은 STEP_MANIFEST 에 없다. `_resolve_model` 은 미등록
    step 을 **gemini-pro 로 조용히 폴백**하므로(실측 2026-07-31: 문항 추출이
    Sol 이 아니라 Gemini 로 갔다), project_config 에 step 을 실어 폴백
    경로를 타지 않게 한다 — `_resolve_model` 은 project_config 에 있는 step
    을 fallback 대상에서 제외한다. 호출자가 이미 지정했으면 그것을 존중한다.
    model)dict
setdefault)step_tagr   project_configcfgs       Y/Users/manta/Documents/Projects/TheRoad-I1/backend/app/modules/pipeline/typology_prior.py
_model_cfgr   _   s+     ~#
$CNN8gu-.J    u  You decide which things at a location are worth looking
up, and which are not.

You get everything the screenplay says about one real place, a structure
spec derived from it, and a list of the things that must be present there.
Some entries carry the source line that put them there.

★ MOST OF THIS NEEDS NO LOOKING UP. Whatever a place of this kind always
has, anyone drawing such a place already knows how it looks. Looking those
up spends the search on what was never in doubt, and — worse — lets them
crowd out the one thing that was.

Keep something ONLY if it meets one of these:
- a place of this kind does NOT always have it, so its ordinary form here
  cannot be assumed; or
- the source line shows the story turns on it, so getting its real form
  wrong would be plainly wrong on screen.

Usually that leaves ONE. Two at most. If nothing qualifies, return an
empty list — that is a good answer, not a failure.

★ JUDGE FROM THE SOURCE LINE, NOT FROM THE NAME. The spec's name for a
thing was written by someone reading the screenplay, and it is often the
nearest ordinary word rather than what actually stands there. The quoted
line is the evidence; the name is not.

For each one you keep, write:
- `target_native`: that one thing, in the plain everyday words local
  people use for it;
- `question_native`: ONE plain question about how it is ordinarily made
  and what it looks like there.

Three hard rules on how you write them:

1. ONE LINE, ONE THING. A question that stacks up material, shape, size,
   surroundings and whether it exists has no answer anywhere and comes
   back empty. Never fold two things into one question.
2. GENERALISE TO THE TYPE. Ask how such a thing is ordinarily made in
   this region — never about this particular story's place. Never name a
   character, a place name, an event, or anything that happens in the
   story, and never carry over its staging, weather, time of day or who
   is present. A reader must not be able to tell which work this came
   from.
3. WRITE IN THE LANGUAGE OF THE SCREENPLAY TEXT you were given, not in
   English. These go into a search engine, and the local convention is
   only documented in the local language.
4. NAME THE REGION AND ERA INSIDE EVERY QUESTION, taking them from the
   confirmed region-and-era block. The searcher is given nothing but your
   questions and your briefing, so a question that says "around here" or
   "in this area" points at nothing and comes back "the region was not
   specified" — measured, and everything asked that way was discarded.
   Write the place and period as words a stranger could search on.

Say in `dropped_reason_ko` (Korean, one line) why the rest were left out.

## ALSO WRITE THE RESEARCHER'S BRIEFING — IN THE SAME LANGUAGE

The person who runs these searches gets one short briefing, and it is the
only thing they read. Write it in the SAME language as the questions,
never in English. It must tell them: search only in this language; look at
the photographs the search returns and not only at the pages; report what
is ORDINARY rather than one striking example; for anything about size,
answer by comparison with what stands in the same view — people, doors,
storeys, rooms — and never in units of measurement, because a measurement
cannot be drawn; describe anything a viewer would SEE closely enough that
someone could draw it, saying how many parts there are, where each sits,
and which colours divide them; and say plainly when nothing was found
rather than reasoning it out.c           	     f    ddt        |       dddddddddddg dd	d
dddddddg dd	S )uR   남길 대상 스키마. `target_native` 는 이미지 질의의 대상이 된다.objectarraystringzbThe one thing, in the plain everyday local words, in the language of the supplied screenplay text.typedescriptionzHONE plain question about how it is ordinarily made there, same language.u.   왜 이것만 남겼는지 한 줄(한국어).)target_nativequestion_nativewhy_kor    
propertiesrequired)r    maxItemsitemszUOne short briefing for the researcher, written in the SAME language as the questions.u+   버린 것들의 사유 한 줄(한국어).)	questionssearch_brief_nativedropped_reason_ko)int)	max_itemss    r   build_gap_schemar/      s       	N$ %-!3* %-!H, %-+[##&!F+: !:$ !L"G'
P*U, ,r   c                   g }| xs g D ]  }t        |t              st        |j                  d      xs d      j	                         }|sCt        t        |j                  d      t              r|j                  d      xs i ni j                  d      xs d      j	                         }|j                  d| |rd| dndz           dj                  |      S )	u  명세가 든 항목을 **원문 인용과 함께** 늘어놓는다.

    ★인용이 근거이고 이름은 근거가 아니다. 이름은 명세를 쓴 쪽이 시나리오를
    읽고 고른 가장 가까운 보통 낱말일 뿐이라, 이름만 주면 실물과 어긋나도
    알 길이 없다(실측: 명세가 붙인 이름 때문에 사진 속 실물을 "없다"고
    판정해 요구된 물건이 통째로 빠졌다). 코드는 무엇이 특별한지 모른다 —
    고르는 것은 이 목록을 읽는 LLM 이다.
    name_en evidencequote_ko- u   
    source line: “u   ”
)
isinstancer   strgetstripappendjoin)
spec_itemslinesitnamequotes        r   build_spec_item_linesrB      s     EB"d#266)$*+113+5z"D,*bffZ &B/133z?IFH
 %' 	 	r$[?D0s;"N 	O  99Ur   r2   )r=   world_facts_blockr.   c                   | xs dj                         st        d      |st        d      g }|xs dj                         r|j                  d|z          |j                  d| z          t        |xs g       }	|	r|j                  d|	z          |xs dj                         r|j                  d|z          |xs dj                         r|j                  d|z          |xs dj                         r|j                  d	|z          |j                  d
dj	                  |      z          |j                  dt        |       d       dj	                  |      S )u  대상 선정 입력 조립 — 시나리오 원문 전문 무절단 (절대 규칙).

    ★`world_facts_block` 이 없으면 문항이 "이 지역"처럼 가리킬 데 없는 말로
    나가고, 조사는 "지역이 명시되지 않았다"로 전건 폐기된다(2026-08-03 실측:
    6그룹 중 2그룹의 조사 4건이 통째로 버려졌다). 확정된 지역·시대는 스텝이
    이미 들고 있었는데 이 경로에만 배선되지 않았다.
    r2   u%   typology_prior: structure_desc 결손uA   typology_prior: 씬 원문 결손 — 근거 없는 문항 차단u}   REGION AND ERA (creator-confirmed — every question you write must name these, because the searcher is given nothing else):
z<STRUCTURE SPEC (what the screenplay was read to establish):
u   THINGS THAT MUST BE PRESENT AT THE PLACE — the name is what someone called it after reading the screenplay; the quoted line is the evidence:
zSITE LAYOUT AS DERIVED:
zINTERIOR EVIDENCE (size only):
zEXTERIOR EVIDENCE:
u   SCREENPLAY SCENES (original language, complete text — this is the primary source and also tells you which language to write your questions in):

z

zReturn at most z questions.)r:   
ValueErrorr;   rB   r<   r-   )
structure_desclayout_narration_eninterior_note_enexterior_note_enscene_blocksr=   rC   r.   parts
item_liness
             r   build_gap_user_contentrM     sc   $  b'')@AA\]]ER&&(*+	, 
LLG
	 'z'7R8J&(23	4 	!r((*03FFGB%%'7:JJKB%%'+.>>?	LL	%{{<8	9
 
LL
#i.)57;;ur   c                &   g }| j                  d      }t        |t              sdgS t        |      |kD  r |j	                  dt        |       d|        t        |      D ]  \  }}t        |t              s|j	                  d| d       ,t        |j                  d      xs d      j                         s|j	                  d| d	       t        |j                  d
      xs d      j                         r|j	                  d| d        |S )u   구조 검증 — 형태와 상한만. **의미 판정은 하지 않는다.**

    무엇이 좋은 대상인지, 어떤 답이 맞는지는 여기서 판정하지 않는다. 글자
    패턴으로 의미를 가르지도 않는다.
    r*   u   questions 가 배열이 아님u   대상 수 u
    > 상한 [u   ] 항목이 객체가 아님r"   r2   u   ] target_native 결손r#   u   ] question_native 결손)	r9   r7   listlenr;   	enumerater   r8   r:   )datar.   
violationsqsiqs         r   validate_gap_outputrX   7  s    J	+	Bb$011
2wKBy
9+FG"1!T"!$@AB155)/R0668!$:;<155*+1r288:!$<=>  r   typology_gap_extract)r=   rC   r   r.   r   c        
           ddl m}
 t        | |||||||      } |
|	t        |t	        |      t        |	t        |      d      }t        ||      }|rt        ddj                  |      z         t        |j                  d      xs g       d	| }t        j                  d
t        |      dj                  d |D              t        |j                  d      xs d      d	d        |t        |j                  d      xs d      j!                         t        |j                  d      xs d      j!                         dS )uT   당연하지 않은 대상만 남겨 한 줄 물음으로 만든다 (검색 없음).r   call_structured)rF   rG   rH   rI   rJ   r=   rC   r.   typology_gapsstepsystem_promptuser_promptresponse_schemar   schema_nameu%   typology_prior 대상 구조 위반: z; r*   Nu>   typology_prior: 남긴 대상 %d개 — %s / 버린 이유: %sz, c              3  P   K   | ]  }t        |j                  d                yw)r"   N)r8   r9   ).0rW   s     r   	<genexpr>z(extract_gap_questions.<locals>.<genexpr>r  s     :r!#aeeO,-rs   $&r,   r2      r+   )r*   r,   r+   )app.modules.llm.llm_clientr\   rM   
GAP_SYSTEMr/   r   	GAP_MODELrX   rE   r<   rP   r9   loggerinforQ   r8   r:   )rF   rG   rH   rI   rJ   r=   rC   r   r.   r   r\   userrS   rT   rU   s                  r   extract_gap_questionsrn   O  s>    ;!%/))!j+yBD ZT(3!(I~F#	%D
 %T95J@499D   		dhh{#)r	*:I	6B
KKH#b'		:r::DHH()/R0#68 !$,-3"55:UW#&./52$77<uw	@ @r   z

Reply with ONE JSON object and nothing else:

{"answers": [{"index": <question number, from 1>,
              "answer_en": "<what you found, in English>",
              "found": true|false,
              "sources": ["<url>", ...]}]}c           
         g }t        | d      D ]E  \  }}|j                  | dt        |j                  d      xs d      j	                                 G dj                  |      S )u6   문항을 번호 붙여 원본어 그대로 넘긴다.   )startz. r#   r2   r6   )rR   r;   r8   r9   r:   r<   )r*   r>   rV   rW   s       r   build_search_userrr     s`    E)1-1s"S'8!9!?R@FFHIJK .99Ur   c                   | xs dj                         }|syt        j                  d|t        j                        }|r|j	                  d      j                         }|j                  d      d}}|dk  ryt        |t        |            D ]W  }||   dk(  r|dz  }||   dk(  s|dz  }|dk(  s%	 t        j                  |||dz          }t        |t              r|c S dc S  y# t        j                  $ r Y  yw xY w)uL   응답 텍스트에서 JSON 객체 하나를 꺼낸다(코드펜스 허용).r2   Nz```(?:json)?\s*(.+?)\s*```rp   {r   })r:   researchSgroupfindrangerQ   jsonloadsJSONDecodeErrorr7   r   )textsfencerq   depthrV   objs          r   _extract_json_objectr     s    	AII3Q=EKKN  "66#;5Eqy5#a&!Q43;QJEqTS[QJEz **QuQU^4C )d3s== "  ++   s   2C''C>=C>)brief_nativec                  |s	|g g ddddS ddl }ddlm}m}m} |xs dj                         t        z   }t        |      }	 |       }
 |d|
      }|j                         }	 | j                  j                  ||dd|	d	gd
gt               gdg      }g }d}|j                  D ]  }|j                   dk(  r>t#        |dd      }t#        |dd      xs t#        |dd      }|s>|j%                  |       P|j                   dk(  s`t#        |dd      xs g D ]  }|t#        |dd      xs dz  }  t'        |      xs i }g }|j)                  d      xs g D ]  }t+        |t,              s	 t        |j)                  d            }d|cxk  rt3        |      k  sn F|j%                  |t        |j)                  d      xs d      j                         t5        |j)                  d            |j)                  d       xs g D cg c]  }|st        |       c}d!        t7        |      \  }} |||| d|	 |rd"ndt        |j                         |z
  dz        |
ddd#| d$| d%t3        |       d&t9        |      xs d' d(	|rdnd)*
       |st;        d+| d,      t<        j?                  d-|||t3        |      tA        d. |D                     ||||j                         ||dS # t        $ rE} |||| d|	 dt        |j                         |z
  dz        |
ddt        |      dd 	        d}~ww xY w# t.        t0        f$ r Y w xY wc c}w )/u   원본어 문항과 **원본어 briefing** 으로 검색해 답한다.

    반환 = {"model", "queries", "answers": [{index, answer_en, found,
    sources[]}], "raw"}
    r2   r   )r   queriesanswersrawsearch_callssearch_completedN)ambient_call_metarecord_provider_callresolve_step_nametypology_priorrm   
input_text)r    r   )rolecontentzweb_search_call.results)r   instructionsinputtoolsincludez
---
errori  
web_searchopenaii  )	r_   r   promptstatusduration_msmeta	operationproviderr   web_search_callactionr   querymessager   r   r   indexrp   	answer_enfoundsources)r   r   r   r   successz[web_search calls=z completed=z	 answers=z+ effort_requested=omitted effort_effective=?]u6   완료된 web_search 가 0 — 조사가 안 돌았다)
r_   r   r   r   r   r   r   r   output_textr   u*   완료된 web_search 가 0 이다 (호출 u.   회) — 이 답은 조사 결과가 아니다uB   typology_prior[%s]: 검색 %d회(완료 %d) / 답 %d개(발견 %d)c              3  ,   K   | ]  }|d    s	d  yw)r   rp   N )re   as     r   rf   z*search_typology_answers.<locals>.<genexpr>  s     5w!!G*Aws   
)!timeapp.modules.llm.image_tracerr   r   r   r:   ANSWER_FORMATrr   	monotonic	responsescreater
   	Exceptionr-   r8   outputr    getattrr;   r   r9   r7   r   	TypeErrorrE   rQ   boolr   r   r	   rk   rl   sum)clientr*   r   r   _timer   r   r   _instructions_user_meta_step_t0resp_excr   saidoactrW   cparsedr   r   idxu_calls_dones                               r   search_typology_answersr     s    2"R !q: 	:
 D D "'R..0=@Mi(EE.6E
//
C&&&")5u EFH I )*+./ ' 
. GD[[66&&!Xt,CY-Lgt1LAq!VVy aD17R762.4"4 8  "$'-2F$&Gjj#)r)!T"	aeeGn%C S*C	N*QUU;/526<<>!%%.))*y)9)?R)?F)?1AA)?F	
 	 *$ +40MFE%=/(H!yw*S0D89lX)&UG D  #G~ .))B4)H)OC(PPQS bW	Y  8 A4 45 	5 KKTvuc'l5w557 w7::<"? ?w  e}oWUG,LU__->-D,L(M,d)DS/		#
 	6 :& 		 Gs7   !2K* *L;M
M*	L83A L33L8;MMu  You compare two independent research results.

For one question about ordinary building convention, two researchers
searched separately and each reported what is typical. Decide whether
they are saying THE SAME THING about the fact being asked.

Agreement is about the fact, not the wording. Two answers agree if
someone drawing the building would draw the same thing from either one.
They disagree if the drawing would differ — a different termination, a
different count, a different arrangement. If one reports a range and the
other a value inside that range, that is agreement, and the agreed fact
is the range. If either researcher found nothing, there is no agreement.

When they agree, write the agreed fact as a single plain sentence stating
what is typical for this kind of structure. Do not add anything neither
researcher reported. Do not mention the researchers, the search, or this
comparison — the sentence will be read on its own.c                 ,    dddddddddddg dd	S )
Nr   booleanzBtrue only if both reported the same fact and both found something.r   r   zIThe agreed typical fact as one plain sentence; empty when agree is false.u8   한국어 한 문장 판정 사유(갤러리 표시용).)agreeagreed_fact_en	reason_kor%   r   r   r   r   build_agree_schemar   0  sD     "' !+ !Y
$ =) r   typology_agreement)r   r   c                p   t        |xr? |j                  d      xr, t        |j                  d      xs d      j                               }t        |xr? |j                  d      xr, t        |j                  d      xs d      j                               }| j                  d      | j                  d      |xs i j                  dd      |xs i j                  dd      t	        h |xs i j                  d      xs g |xs i j                  d      xs g       d}|s|si |ddd	d
ddS ||k7  rJ|r|n|}|rdnd}	i |dddd|	 dt        |xs i j                  d      xs d      j                         dS ||i |ddd	dddS ddlm}
 dt        | j                  d      xs d      z   dz   t        |j                  d      xs d      z   dz   t        |j                  d      xs d      z   } |
|t        |t               t        |t        |      d      }t        |j                  d            }t        |j                  d      xs d      j                         }|xr t        |      }i ||||rdnd	|r|ndt        |j                  d      xs d      j                         dS )uU   두 답의 일치를 판정한다. 한쪽이라도 미발견이면 LLM 없이 폐기.r   r   r2   r"   r#   r   )r"   r#   answer_aanswer_br   Fnoneu)   양쪽 모두 근거 미발견 — 폐기)adoptedr   strengthr   r   ABTweaku   한쪽(uG   )만 근거 확보 — 단독 근거로 약하게 채택(단정 아님)u   답 결손 — 폐기r   r[   zQUESTION (original language):
z

RESEARCHER A:
z

RESEARCHER B:
typology_agreer^   r   r   strongr   )r   r   r   r   r   )r   r9   r8   r:   sortedrh   r\   AGREE_SYSTEMr   r   AGREE_MODEL)questionr   r   r   r   a_okb_okbasesolowhor\   rm   rS   r   factr   s                   r   combine_typology_answersr   I  s     AX\\'2 A[17R8>>@BD AX\\'2 A[17R8>>@BD "o6#<<(9:^((b9^((b9 
~2""9-3
~2""9-3
 	D &$ &55fH"$& 	& t|xXcs3$ 34%V 'u -@ A"%tzr&6&6{&C ')&(#**/%'	3 	3 8+L$ L55f4L 	L ; 	*
hll,-3
4	5
	 "%hll;&?&E2"F	G  	  #&hll;&?&E2"F	G 	 \t*,!(KH$	&D
 '"#Etxx()/R0668D"T
GCd Cw$+&-d2TXXk28b9??AC Cr   u  RESEARCHED FACTS — what a place of this KIND actually looks like, looked up from real examples (photographs included) because neither the screenplay nor the STRUCTURE SPEC says anything about it:
Where the screenplay or the STRUCTURE SPEC settles a matter, that wins and you ignore the line below. EVERYWHERE ELSE THESE FACTS SETTLE IT — they are here to replace your own impression of the type, which is what would otherwise fill the gap. Write what they describe into the picture as concrete visual fact, in the same plain physical sentences as everything else. They are about the type and not about this particular place, so never present them as something the screenplay stated. Never state the absence of something merely because it is not listed here.uL  
Each line is marked [corroborated] when both researchers reported the same thing, or [single source] when only one found a basis. Treat a [single source] line as a tendency worth following, not as a fact to assert — never write it into the brief as something the place certainly has, and never let it force a count or a negation.z
If a line mentions a real name it saw on an example, that is an observation about how such places are named, never a name to reuse. This place's own name comes from what the screenplay supplies.c                   g g }}| D ]  }|j                  d      st        |j                  d      xs d      j                         }|sDt        |j                  d      xs d      j                         }|rd| dnd}|j                  d      d	k(  r|j                  | d
|        |j                  | d|         ||z   }|syt        t
        z   t        z   dz   dj                  |      z   S )u  채택된 사실을 저작 입력 블록으로 만든다. 없으면 빈 문자열.

    ★단독 근거는 버리지 않고 등급을 붙여 넘긴다 — 초판이 한쪽 미발견을
    폐기하는 바람에 가장 필요한 항목이 사라졌다(2026-07-31 실측).

    라벨은 **조사한 대상 그 자체**(원어)다. v2 의 축 이름은 그 축들을
    없애면서 함께 사라졌다.
    r   r   r2   r"   z- (z) r5   r   r   z[single source] z[corroborated] r6   )r9   r8   r:   r;   FACTS_BLOCK_HEADER_STRENGTH_NOTE_OBSERVED_NAME_NOTEr<   )r   r   r   itemr   labelheadr>   s           r   build_typology_facts_blockr     s     rDFxx	"488,-34::<DHH_-34::<"'UG2T88J6)KK4& 078MMTF/$89  TME/2EEYYu%& 'r   c                    | j                  d      xs g }t        d |D              }dt        |       d| dt        |      |z
   S )u   로그 한 줄 요약.r)   c              3  D   K   | ]  }|j                  d       sd  yw)r   rp   N)r9   )re   rV   s     r   rf   zsummarize.<locals>.<genexpr>  s     21y!1Qs     u   문항 u    · 채택 u    · 폐기 )r9   r   rQ   )recordr)   ads      r   	summarizer     sK    JJw%2E	22	2Bc%j\RDCJO;LMNr   )r   r8   r   r8   r   Optional[Dict[str, Any]]returnDict[str, Any])r.   r-   r   r   )r=   Sequence[Dict[str, Any]]r   r8   )rF   r8   rG   r8   rH   r8   rI   r8   rJ   Sequence[str]r=   "Optional[Sequence[Dict[str, Any]]]rC   r8   r.   r-   r   r8   )rS   r   r.   r-   r   z	List[str])rF   r8   rG   r8   rH   r8   rI   r8   rJ   r   r=   r   rC   r8   r   r   r.   r-   r   r8   r   r   )r*   r   r   r8   )r   r8   r   r   )
r   r   r*   r   r   r8   r   r8   r   r   )r   r   )r   r   r   r   r   r   r   r   r   r8   r   r   )r   r   r   r8   )r   r   r   r8   ),__doc__
__future__r   r|   loggingrv   typingr   r   r   r   r   (app.modules.pipeline.search_grounded_refr	   r
   r   r   	getLogger__name__rk   TYPOLOGY_PRIOR_VERSIONMAX_GAP_QUESTIONSSEARCH_MODELSrj   r   r   ri   r/   rB   rM   rX   rn   r   rr   r   r   r   r   r   r   r   r   r   r   r   r   r   <module>r     s  (R #   	 6 6
  
		8	$     /	7<J$C!
L '8 .b@ 6:&33 3 	3
 3  3 33 3 3 	3n *;#&?H> 6:/3&*)@)@ )@ 	)@
 )@  )@ 3)@ )@ -)@ )@ )@ )@f.< j?j? (j? 	j?
 j? j?`8&< 04(ICIC 'IC '	IC
 -IC IC ICl6 "C E '%'*-'<Or   