§
    éƒtjwh  ã                  óH  — U d Z ddlmZ ddlZddlZddlZddlZddlmZm	Z	 ddl
mZ ddlmZ ddlZddlmZ ddlmZ dd	lmZmZ dd
lmZmZ ddlmZmZmZmZmZmZm Z m!Z!m"Z"m#Z# ddl$m%Z& ddl$m'Z' ddl(m)Z) ddl*m+Z+ ddl*m,Z,m-Z-m.Z. ddl/m0Z0 h d£Z1h d£Z2h d£Z3h d£Z4 ej5        d¦  «        Z6 ej5        d¦  «        Z7 ej5        dej8        ¦  «        Z9 ej5        dej8        ¦  «        Z: ej5        d¦  «         ej5        d¦  «         ej5        d¦  «         ej5        d¦  «        gZ; ej5        d¦  «        Z< ej5        d¦  «        Z= ej5        d ¦  «        Z>d9d$„Z?d:d'„Z@d;d)„ZAd*d+œd<d-„ZB ed.„ ¦  «        ZCd/eDd0<   d=d4„ZEee"eeeed5œZF G d6„ d7¦  «        ZGed>d8„¦   «         ZHdS )?u5   RAG chatbot service â€” retrieval + Ollama reasoning.é    )ÚannotationsN)ÚdefaultdictÚdeque)ÚIterator)Ú	lru_cache)ÚHuggingFaceEmbeddings)ÚChroma)ÚSettingsÚget_settings)ÚChatResponseÚCitation)
Ú
BYE_PROMPTÚCONCEPT_PROMPTÚGREETING_PROMPTÚHELP_PROMPTÚNO_DATA_PROMPTÚOFFTOPIC_PROMPTÚPDF_SYSTEM_PROMPTÚSYSTEM_PROMPTÚTHANKS_PROMPTÚUSER_PROMPT)Ú	calculate)Úis_pure_math)Úrun_structured_query)Úformat_job_context)Ú answer_statement_metric_questionÚis_pdf_overview_questionÚdescribe_pdf_job)Úget_session_job>/   úyou okúhow r uúwhats upúyou goodú	hey thereú	how are uú	how r youú	what's upú
whats goodúhow are youúwhat's goodúgood eveningúgood morningúhow you doingúhows it goingúgood afternoonúhow's it goingúhow is it goingúhow are you doingúhow have you beenÚhÚheÚhiÚyoÚhaiÚhelÚheyÚhhiÚhiiÚsupÚhellÚheloÚhlloÚholaÚhalloÚheeloÚhelloÚhellpÚhelooÚhowdyÚhulloÚkelloÚkellooÚwassupÚwassuppÚwhassupÚwhatsup>   úthank uú	thank youÚthxÚthanks>   úsee yaúsee youÚbyeÚgoodbye>   úhelp meú	about youú	who r youúwho are youúabout yourselfúwhat can you doúhow can you helpútell me about youúhow can you help meútell me about the botútell me about this botútell me about yourselfúwhat can you help withúwhat can you help me withútell me about the assistantÚhelpa  (?i)\b(how\s+can\s+you\s+help(?:\s+me)?|what\s+can\s+you\s+(?:do|help(?:\s+me)?(?:\s+with)?)|what\s+do\s+you\s+know|who\s+(?:are|r)\s+you|tell\s+me\s+about\s+(?:yourself|you|the\s+bot|this\s+bot|the\s+assistant|alex)|(?:about\s+yourself|about\s+you)\b|help\s+me\b|\bhelp\b)\bzÜ(?i)^(how\s+are\s+(?:you|u)(?:\s+doing)?|how(?:'s|\s+is)\s+it\s+going|how\s+have\s+you\s+been|how\s+you\s+doing|you\s+(?:good|ok|okay)|(?:what'?s|whats)\s+up|wass?u+p+|whass?u+p+|(?:what'?s|whats)\s+good|yo|sup)[?.!\s]*$aª  \b(weather|football|cricket|movie|song|joke|recipe|(?:write|debug|run)\s+code|python\s+code|javascript\s+code|programming|bitcoin price today|horoscope|dating|girlfriend|boyfriend|capital\s+of|who\s+invented|who\s+discovered|photosynthesis|gravity|solar\s+system|planet|continent|ocean|mountain|president\s+of|population\s+of|distance\s+between|how\s+tall\s+is|how\s+old\s+is\s+(?:the|earth)|tell\s+me\s+a\s+joke|fun\s+fact)\baS  ^\s*(what\s+is|what\s+are|what\'s|define|definition\s+of|explain|meaning\s+of|how\s+does|how\s+do|difference\s+between|why\s+is|why\s+are|who\s+(?:is|was|invented|discovered|wrote|painted)|where\s+is|when\s+was|when\s+did|which\s+(?:country|city|planet)|tell\s+me\s+about(?!\s+(?:my|the\s+statement|the\s+pdf|the\s+document|this\s+pdf)))\bz(?im)^\s*sources?\s*:.*$z(?im)^\s*note\s+\d+\s*:.*$z(?i)\b(record_id|txn_\d+|source\s*\d+|dataset|knowledge base|RAG|vector|structured results?|line item totals|reference notes)\bz?(?im)^\s*(as an ai|based on (the )?(context|notes|provided)).*$zN(?i)\b(goodbye|good bye|bye for now|take care|see you|farewell)\b[^.!?]*[.!?]?uj   (?is)^[\"â€œ]?[^\"â€�\n]+\.pdf[\"â€�]?\s+is a balance sheet with \d+ line items\.\s*Key balances:.*Ratios:u=   (?is)^Loaded\s+[\"â€œ].+[\"â€�]\.?\s*(Ask what|You can ask).+ÚtextÚstrÚreturnc                ón  — |                       ¦   «                              ¦   «         }t          j        dd|¦  «                              ¦   «         }t          j        dd|¦  «        }t          j        dd|¦  «                              ¦   «         }t          j        dd|¦  «                              ¦   «         }|S )Nz	[^\w\s]+$Ú z^alex[,.]?\s+z\s+alex$)ÚstripÚlowerÚreÚsub)rg   Úss     ú)/var/www/html/CA-Chatbot/app/rag/chain.pyÚ_normalize_smalltalkrr   �   s‘   € Ø�
Š
‰Œ×ÒÑÔ€Aå
Œˆ|˜R Ñ#Ô#×)Ò)Ñ+Ô+€AÝ
ŒÐ  QÑ'Ô'€AÝ
Œˆ{˜B Ñ"Ô"×(Ò(Ñ*Ô*€AÝ
Œˆ|˜R Ñ#Ô#×)Ò)Ñ+Ô+€AØ€Hó    ÚnormÚboolc                óô   — | sdS | t           v s| dk    rdS t          | ¦  «        dk    s(|                      dd¦  «                             ¦   «         sdS t	          t          j        | g d¢dd	¬
¦  «        ¦  «        S )u<   Typo-tolerant hello/hi/hey detection (e.g. KELLO â†’ hello).FÚalexTé
   Ú rk   )rD   r6   r:   rG   rA   é   g
×£p=
ç?)ÚnÚcutoff)Ú_GREETING_WORDSÚlenÚreplaceÚisalpharu   ÚdifflibÚget_close_matches)rt   s    rq   Ú_likely_greetingrƒ   ™   s‹   € àð ØˆuØ�ÐÐ $¨&¢. .ØˆtÝ
ˆ4�y„y�2‚~€~˜TŸ\š\¨#¨rÑ2Ô2×:Ò:Ñ<Ô<€~ØˆuÝÝÔ! $Ð(OÐ(OÐ(OÐSTÐ]aÐbÑbÔbñô ð rs   Úquestionc                óÚ  — |                       ¦   «         }|sdS t          |¦  «        }|t          v rdS |t          v rdS |t          v s_t
                               |                     d¦  «        d                               ¦   «         ¦  «        st
                               |¦  «        r,t          j        d|¦  «        st          j        d|¦  «        sdS |t          v s/|d	k    s)t                               |¦  «        st          |¦  «        rdS t          |¦  «        d
k    r+|                     ¦   «         rt          j        d|¦  «        sdS t          j        d|¦  «        rdS t                               |¦  «        rdS t!          |¦  «        rdS t                               |¦  «        rdS t"                               |¦  «        r't          |                     ¦   «         ¦  «        dk    rdS dS )zBReturn: greeting | thanks | bye | help | offtopic | concept | dataÚgreetingrU   rR   Ú,r   z-(?i)\b(analy[sz]e|summar(?:y|ize)|overview)\bz=(?i)\b(spend|spent|payment|merchant|statement|pdf|document)\brf   rw   é   z\dz_^(hi+|hii|hhi|hello+|hey+|good morning|good afternoon|good evening|howdy|yo)(\s+(alex|there))?$ÚofftopicÚmathé   ÚconceptÚdata)rl   rr   Ú
_BYE_WORDSÚ_THANKS_WORDSÚ_HELP_WORDSÚ_HELP_REÚsearchÚsplitrn   r}   Ú_HOW_ARE_YOU_REÚmatchrƒ   r~   r€   Ú_OFFTOPIC_REr   Ú_CONCEPT_RE)r„   rg   rt   s      rq   Ú_detect_intentr˜   ¦   sØ  € à�>Š>ÑÔ€DØð Øˆzå Ñ%Ô%€Dà�zÐÐØˆuØ�}ÐÐØˆxð 
•Ð	Ð	¥§¢°·
²
¸3±´ÀÔ0B×0HÒ0HÑ0JÔ0JÑ KÔ KÐ	ÍxÏÊÐ_cÑOdÔOdÐ	Ý”	ÐJÈDÑQÔQð 
å”	ÐZÐ\`ÑaÔað 
ð ˆvØ�ÐÐ $¨&¢. .µO×4IÒ4IÈ$Ñ4OÔ4O .ÕScÐdhÑSiÔSi .Øˆzå
ˆ4�y„y�A‚~€~˜$Ÿ,š,™.œ.€~µ´¸5À$Ñ1GÔ1G€~ØˆzÝ	„xð	àñô ð ð
 ˆzÝ×Ò˜4Ñ Ô ð ØˆzÝ�DÑÔð Øˆvå×Ò˜TÑ"Ô"ð ØˆzÝ×Ò˜$ÑÔð ¥C¨¯
ª
©¬Ñ$5Ô$5¸Ò$;Ð$;ØˆyØˆ6rs   F©Úallow_goodbyerš   c               ó¤  ‡— |                       ¦   «         }t          j        dd|t          j        ¬¦  «        }g }|                     ¦   «         D ]@Št          ˆfd„t          dd…         D ¦   «         ¦  «        rŒ+|                     ‰¦  «         ŒAd                     |¦  «                              ¦   «         }t          d                              d|¦  «        }|st                               d|¦  «        }t          j
        d|¦  «        }|r|d	                               ¦   «         n|}t          j
        d
|¦  «        }t          |¦  «        dk    r/d                     |dd…         ¦  «                              ¦   «         }t          j        dd|¦  «                              ¦   «         }t          j        dd|¦  «                              ¦   «         }|pdS )z:Strip model artifacts and enforce a single coherent reply.z^(Alex|Assistant|Reply)\s*:\s*rk   )Úflagsc              3  óB   •K  — | ]}|                      ‰¦  «        V — Œd S ©N)r’   )Ú.0ÚpÚlines     €rq   ú	<genexpr>z _clean_answer.<locals>.<genexpr>×   s-   øè è € Ð:Ð: !ˆq�xŠx˜‰~Œ~Ð:Ð:Ð:Ð:Ð:Ð:rs   Nrˆ   Ú
z\n\s*\nr   z(?<=[.!?])\s+é   ry   z\s{2,}z\n{3,}ú

z;I don't have enough information to answer that confidently.)rl   rn   ro   Ú
IGNORECASEÚ
splitlinesÚanyÚ_LEAK_PATTERNSÚappendÚjoinÚ_GOODBYE_REr“   r~   )rg   rš   ÚcleanedÚlinesÚpartsÚ	sentencesr¡   s         @rq   Ú_clean_answerr±   Ð   s§  ø€ à�jŠj‰lŒl€GÝŒfÐ6¸¸GÍ2Ì=ÐYÑYÔY€Gà€EØ×"Ò"Ñ$Ô$ð ð ˆÝÐ:Ð:Ð:Ð:¥~°b°q°bÔ'9Ð:Ñ:Ô:Ñ:Ô:ð 	ØØ�Š�TÑÔÐÐØ�iŠi˜ÑÔ×$Ò$Ñ&Ô&€GÝ˜QÔ×#Ò# B¨Ñ0Ô0€Gàð /Ý—/’/ " gÑ.Ô.ˆõ ŒH�Z Ñ)Ô)€EØ"'Ð4ˆe�AŒh�nŠnÑÔÐ¨W€Gõ ”Ð)¨7Ñ3Ô3€IÝ
ˆ9�~„~˜ÒÐØ—(’(˜9 R a Rœ=Ñ)Ô)×/Ò/Ñ1Ô1ˆåŒf�Y  WÑ-Ô-×3Ò3Ñ5Ô5€GÝŒf�Y ¨Ñ0Ô0×6Ò6Ñ8Ô8€GØÐSÐSÐSrs   c                 ó"   — t          d¬¦  «        S )Nr¤   )Úmaxlen)r   © rs   rq   ú<lambda>rµ   ï   s   € Í%ÐWXÈ/É/Ì/€ rs   z!dict[str, deque[tuple[str, str]]]Ú_SESSION_HISTORYÚ
session_idú
str | NoneÚNonec                óD   — | sd S t                                | d ¦  «         d S rž   )r¶   Úpop)r·   s    rq   Úclear_session_historyr¼   ò   s+   € Øð ØˆÝ×Ò˜ TÑ*Ô*Ð*Ð*Ð*rs   )r†   rR   rU   rf   r‰   rŒ   c                  óÔ   — e Zd Zd8d„Zed9d„¦   «         Zd:d„Zd;d
„Zd<d„Zd=d„Z	d>d„Z
d>d„Zd?d„Zd@d„ZdAd„ZdBdCd„ZdDd„ZdEd$„Zdd%œdFd'„Zdd%œdGd(„ZdHd*„ZdId+„Zd,d-œdJd6„ZdBdKd7„ZdS )LÚ
RAGServiceÚsettingsr
   c                ób   — || _         t          |j        ddiddi¬¦  «        | _        d | _        d S )NÚdeviceÚcpuÚnormalize_embeddingsT)Ú
model_nameÚmodel_kwargsÚencode_kwargs)r¿   r   Úembedding_modelÚ_embeddingsÚ_vectorstore)Úselfr¿   s     rq   Ú__init__zRAGService.__init__  sF   € Ø ˆŒÝ0ØÔ/Ø" EÐ*Ø1°4Ð8ð
ñ 
ô 
ˆÔð
 ,0ˆÔÐÐrs   ri   r   c                ó   — | j         S rž   )rÈ   ©rÊ   s    rq   Ú
embeddingszRAGService.embeddings  s   € àÔÐrs   r	   c                óÚ   — | j         €^| j        j                             dd¬¦  «         t	          | j        j        | j        t          | j        j        ¦  «        ¬¦  «        | _         | j         S )NT)ÚparentsÚexist_ok)Úcollection_nameÚembedding_functionÚpersist_directory)rÉ   r¿   Úchroma_persist_dirÚmkdirr	   Úchroma_collectionrÈ   rh   rÍ   s    rq   Úget_vectorstorezRAGService.get_vectorstore  si   € ØÔÐ$ØŒMÔ,×2Ò2¸4È$Ð2ÑOÔOÐOÝ &Ø $¤Ô ?Ø#'Ô#3Ý"% d¤mÔ&FÑ"GÔ"Gð!ñ !ô !ˆDÔð
 Ô Ð rs   ÚOllamac                óú   — | j         €n| j        j        | j        j        d| j        j        | j        j        ddœ}| j        j        pt                               ¦   «         }|r||d<   t          di |¤Ž| _         | j         S )Nç        Ú30m)Úbase_urlÚmodelÚtemperatureÚnum_ctxÚnum_predictÚ
keep_aliveÚ
num_threadr´   )
Ú_llmr¿   Úollama_base_urlÚollama_modelÚollama_num_ctxÚollama_num_predictÚollama_num_threadsÚosÚ	cpu_countrÙ   )rÊ   Ú
llm_kwargsÚthreadss      rq   Úget_llmzRAGService.get_llm  s„   € ØŒ9Ðà œMÔ9ØœÔ3Ø"Øœ=Ô7Ø#œ}Ô?à#ð ð  ˆJð ”mÔ6ÐH½"¿,º,¹.¼.ˆGØð 3Ø+2�
˜<Ñ(ÝÐ,Ð, Ð,Ð,ˆDŒIØŒyÐrs   r¹   c                ó€   — |                       ¦   «          	 |                      dd¬¦  «         dS # t          $ r Y dS w xY w)z>Pre-load embeddings, vector store, and keep Ollama model warm.r6   é   ©rá   N)Údocument_countÚ_invoke_ollamaÚ	ExceptionrÍ   s    rq   ÚwarmupzRAGService.warmup*  sZ   € à×ÒÑÔÐð	Ø×Ò °!ÐÑ4Ô4Ð4Ð4Ð4øÝð 	ð 	ð 	ØˆDˆDð	øøøs   –/ ¯
=¼=ú
int | Nonec                ó€   — 	 |                       ¦   «         }|j                             ¦   «         S # t          $ r Y d S w xY wrž   )rØ   Ú_collectionÚcountrô   )rÊ   Ústores     rq   rò   zRAGService.document_count2  sO   € ð	Ø×(Ò(Ñ*Ô*ˆEØÔ$×*Ò*Ñ,Ô,Ð,øÝð 	ð 	ð 	Ø�4�4ð	øøøs   ‚,/ ¯
=¼=ru   c                ó>   — |                       ¦   «         }|d uo|dk    S )Nr   )rò   )rÊ   rù   s     rq   Úvector_store_readyzRAGService.vector_store_ready9  s'   € Ø×#Ò#Ñ%Ô%ˆØ˜DÐ Ð. U¨Q¢YÐ.rs   c              ƒ  ó  K  — 	 t          j        d¬¦  «        4 ƒd {V —†}|                     | j        j        › d�¦  «        ƒ d {V —†}|j        dk    cd d d ¦  «        ƒd {V —† S # 1 ƒd {V —†swxY w Y   d S # t          $ r Y dS w xY w)Ng      @©Útimeoutz	/api/tagséÈ   F)ÚhttpxÚAsyncClientÚgetr¿   rå   Ústatus_coderô   )rÊ   ÚclientÚresponses      rq   Úollama_reachablezRAGService.ollama_reachable=  s:  è è € ð	ÝÔ(°Ð5Ñ5Ô5ð 3ð 3ð 3ð 3ð 3ð 3ð 3¸Ø!'§¢¨t¬}Ô/LÐ,WÐ,WÐ,WÑ!XÔ!XÐXÐXÐXÐXÐXÐX�ØÔ+¨sÒ2ð3ð 3ð 3ð 3ñ 3ô 3ð 3ð 3ð 3ð 3ð 3ð 3ð 3ð 3ð 3ð 3ð 3ð 3ð 3ð 3ð 3ð 3ð 3ð 3øøøð 3ð 3ð 3ð 3ð 3ð 3øõ ð 	ð 	ð 	Ø�5�5ð	øøøs4   „A8 Ÿ3A%ÁA8 Á%
A/Á/A8 Á2A/Á3A8 Á8
BÂBútuple[str, list[Citation]]c           	     óV  — g }g }t          |d¬¦  «        D ]ý\  }}|j        }|                     dd|› �¦  «        }|                     dd¦  «        }|                     dd¦  «        }	|j        d d…                              ¦   «         }
| j        j        }|j        d |…                              ¦   «         }t          |j        ¦  «        |k    r|d	z  }|                     d
|› d|› �¦  «         |                     t          |||	|
¬¦  «        ¦  «         Œþd 
                    |¦  «        |fS )Nrz   )ÚstartÚ	record_idÚchunk_Údata_categoryÚunknownÚsource_dataseti�  z...zNote z:
)r  r  r  Úexcerptz

---

)Ú	enumerateÚmetadatar  Úpage_contentrl   r¿   Úmax_context_chars_per_docr~   rª   r   r«   )rÊ   ÚdocsÚblocksÚ	citationsÚidxÚdocÚmetar  ÚcategoryÚsourcer  Ú	max_charsÚcontents                rq   Ú_format_contextzRAGService._format_contextE  sP  € ØˆØ$&ˆ	å! $¨aÐ0Ñ0Ô0ð 	ð 	‰HˆC�Ø”<ˆDØŸš ¨n°s¨n¨nÑ=Ô=ˆIØ—x’x °Ñ;Ô;ˆHØ—X’XÐ.°	Ñ:Ô:ˆFØÔ& t¨ tÔ,×2Ò2Ñ4Ô4ˆGØœÔ?ˆIØÔ& z¨	 zÔ2×8Ò8Ñ:Ô:ˆGÝ�3Ô#Ñ$Ô$ yÒ0Ð0Ø˜5Ñ �à�MŠMÐ3 #Ð3Ð3¨'Ð3Ð3Ñ4Ô4Ð4Ø×ÒÝØ'Ø"*Ø#)Ø#ð	ñ ô ñô ð ð ð ×!Ò! &Ñ)Ô)¨9Ð4Ð4rs   r·   r¸   rh   c                óü   — |sdS t                                |¦  «        }|sdS dg}|D ]=\  }}|                     d|› �¦  «         |                     d|d d…         › �¦  «         Œ>d                     |¦  «        dz   S )Nrk   zRecent conversation:zUser: zAlex: é´   r£   r¥   )r¶   r  rª   r«   )rÊ   r·   Úturnsr®   ÚqÚas         rq   Ú_history_blockzRAGService._history_block`  sŸ   € Øð 	Ø�2Ý ×$Ò$ ZÑ0Ô0ˆØð 	Ø�2Ø'Ð(ˆØð 	-ð 	-‰DˆAˆqØ�LŠL˜ !˜˜Ñ&Ô&Ð&Ø�LŠLÐ+ ! D S D¤'Ð+Ð+Ñ,Ô,Ð,Ð,Ø�yŠy˜ÑÔ &Ñ(Ð(rs   r„   Úanswerc                óR   — |sd S t           |                              ||f¦  «         d S rž   )r¶   rª   )rÊ   r·   r„   r&  s       rq   Ú	_rememberzRAGService._rememberl  s3   € Øð 	ØˆFÝ˜Ô$×+Ò+¨X°vÐ,>Ñ?Ô?Ð?Ð?Ð?rs   Nc                ób  ‡— |                       ¦   «         }|}|r\t                               |¦  «        rBt          |         d         \  }}t          |                     ¦   «         ¦  «        dk    r|› d|› �}|                     || j        j        ¬¦  «        }| j        j        Šˆfd„|D ¦   «         S )z@Retrieve relevant docs, optionally biased by last user question.éÿÿÿÿrð   r£   )Úkc                ó*   •— g | ]\  }}|®|‰k    ¯|‘ŒS rž   r´   )rŸ   r  ÚscoreÚ	thresholds      €rq   ú
<listcomp>z(RAGService._retrieve.<locals>.<listcomp>~  s,   ø€ ÐYÐYÐY™
˜˜U°Ð0AÀeÈyÒFXÐFX�ÐFXÐFXÐFXrs   )	rØ   r¶   r  r~   r“   Ú'similarity_search_with_relevance_scoresr¿   Úretrieval_top_kÚsimilarity_threshold)	rÊ   r„   r·   rú   ÚqueryÚlast_qÚ_Úscoredr.  s	           @rq   Ú	_retrievezRAGService._retrieveq  sÄ   ø€ à×$Ò$Ñ&Ô&ˆØˆØð 	0Õ*×.Ò.¨zÑ:Ô:ð 	0Ý(¨Ô4°RÔ8‰IˆF�AÝ�8—>’>Ñ#Ô#Ñ$Ô$¨Ò)Ð)Ø!Ð/Ð/ XÐ/Ð/�à×>Ò>Ø�T”]Ô2ð ?ñ 
ô 
ˆð ”MÔ6ˆ	ØYÐYÐYÐY fÐYÑYÔYÐYrs   rá   útuple[int, bool, float, str]c                ó  — | j         j        }|�|n| j         j        }|rt          || j         j        ¦  «        }nt          || j         j        ¦  «        }| j         j                             d¦  «        }| j         j        |rdndz  }||||fS )Nú/g       @g      ð?)	r¿   Úollama_thinkrè   ÚmaxÚollama_num_predict_thinkingÚollama_num_predict_minrå   ÚrstripÚollama_timeout)rÊ   rá   ÚthinkÚpredictÚbaserÿ   s         rq   Ú_ollama_predictzRAGService._ollama_predict€  s‘   € Ø”Ô*ˆØ!,Ð!8�+�+¸d¼mÔ>^ˆØð 	IÝ˜' 4¤=Ô#LÑMÔMˆGˆGå˜' 4¤=Ô#GÑHÔHˆGØŒ}Ô,×3Ò3°CÑ8Ô8ˆØ”-Ô.¸Ð2G°#°#ÀCÑHˆØ˜˜w¨Ð,Ð,rs   ÚpromptÚintÚ	use_thinkÚdictc          	     óL   — | j         j        d|dœgd|dd| j         j        |dœdœS )NÚuser)Úroler  FrÜ   rÛ   )rß   rà   rá   )rÞ   ÚmessagesÚstreamrA  râ   Úoptions)r¿   ræ   rç   )rÊ   rE  rá   rG  s       rq   Ú_ollama_chat_payloadzRAGService._ollama_chat_payload‹  sJ   € ð ”]Ô/Ø"(°VÐ<Ð<Ð=ØØØà"Øœ=Ô7Ø*ðð ð
ð 
ð 	
rs   rñ   úIterator[str]c          
   #  ó&  K  — |                       |¦  «        \  }}}}|                      |||¬¦  «        }d|d<   	 t          j        |¬¦  «        5 }|                     d|› d�|¬¦  «        5 }	|	j        dk    r!| j        j        }
t          d	|
› d
|
› �¦  «        ‚|	j        dk    rFt          d|	j        › d|	 	                    ¦   «          
                    ¦   «         dd…         › �¦  «        ‚|	                     ¦   «         D ]‹}|sŒ	 t          j        |¦  «        }n# t          j        $ r Y Œ,w xY w|                     d¦  «        x}rt          d|› �¦  «        ‚|                     d¦  «        pi                      d¦  «        pd}|r|V — ŒŒ	 ddd¦  «         n# 1 swxY w Y   ddd¦  «         dS # 1 swxY w Y   dS # t          j        $ r}t          d|› d|› �¦  «        |‚d}~wt          $ r ‚ t"          $ r}t          d|› �¦  «        |‚d}~ww xY w)z3Stream visible answer tokens from Ollama /api/chat.©rá   rG  TrM  rþ   ÚPOSTú	/api/chat©Újsoné”  úOllama model 'ú+' was not found. Pull it with: ollama pull r   úOllama returned HTTP ú: Néô  ÚerrorúOllama error: Úmessager  rk   úOllama timed out after ús at úOllama request failed: )rD  rO  r  ÚClientrM  r  r¿   ræ   ÚRuntimeErrorÚreadÚdecodeÚ
iter_linesrV  ÚloadsÚJSONDecodeErrorr  ÚTimeoutExceptionrô   )rÊ   rE  rá   rB  rA  rÿ   rC  Úpayloadr  r  rÄ   r¡   r�   ÚerrÚchunkÚexcs                   rq   Ústream_ollamazRAGService.stream_ollama›  sQ  è è € ð )-×(<Ò(<¸[Ñ(IÔ(IÑ%ˆ�˜ Ø×+Ò+¨FÀÐSXÐ+ÑYÔYˆØ ˆ�Ñð!	IÝ” gÐ.Ñ.Ô.ð (°&Ø—]’] 6¨dÐ+=Ð+=Ð+=ÀG�]ÑLÔLð (ÐPXØÔ+¨sÒ2Ð2Ø%)¤]Ô%?˜
Ý*ðF¨Zð Fð FØ9CðFð Fñô ð ð  Ô+¨sÒ2Ð2Ý*ð@°HÔ4Hð @ð @Ø'Ÿ}š}™œ×5Ò5Ñ7Ô7¸¸¸Ô=ð@ð @ñô ð ð !)× 3Ò 3Ñ 5Ô 5ð (ð (˜Ø#ð %Ø$ð%Ý#'¤:¨dÑ#3Ô#3˜D˜DøÝ#Ô3ð %ð %ð %Ø$˜Hð%øøøà"&§(¢(¨7Ñ"3Ô"3Ð3˜3ð GÝ".Ð/EÀÐ/EÐ/EÑ"FÔ"FÐFØ!%§¢¨)Ñ!4Ô!4Ð!:¸× ?Ò ?À	Ñ JÔ JÐ PÈb˜Ø ð (Ø"'˜K˜K˜Køð(ð(ð (ð (ñ (ô (ð (ð (ð (ð (ð (ð (øøøð (ð (ð (ð (ð(ð (ð (ñ (ô (ð (ð (ð (ð (ð (ð (ð (øøøð (ð (ð (ð (ð (ð (øõ2 Ô%ð 	ð 	ð 	ÝØ>¨'Ð>Ð>¸Ð>Ð>ñô àðøøøøõ ð 	ð 	ð 	ØÝð 	Ið 	Ið 	IÝÐ>¸Ð>Ð>Ñ?Ô?ÀSÐHøøøøð	Iøøøs‘   »F< ÁF/Á,BFÄDÄFÄD+	Ä(FÄ*D+	Ä+AFÆF/ÆF	ÆF/ÆF	ÆF/Æ"F< Æ/F3Æ3F< Æ6F3Æ7F< Æ<HÇG!Ç!HÇ8HÈHc               óü  ‡ ‡‡	‡
— ‰                       |¦  «        \  }}Š
Š	dˆ	ˆˆ ˆ
fd„} |||¬¦  «        \  }}|                     ¦   «         sQ|r1t          |d	z  ‰ j        j        d	z  ¦  «        } ||d
¬¦  «        \  }}n |t          |d¦  «        d¬¦  «        \  }}|                     ¦   «         s9|                     d¦  «        dk    r t          d|› d‰ j        j        › d�¦  «        ‚|                     ¦   «         S )zLCall Ollama /api/chat (same API as curl) on the configured GPU/local server.rá   rF  rG  ru   ri   útuple[dict, str]c               óö  •— ‰                      ‰| |¬¦  «        }	 t          j        ‰¬¦  «        5 }|                     ‰
› d�|¬¦  «        }d d d ¦  «         n# 1 swxY w Y   nM# t          j        $ r}t          d‰› d‰
› �¦  «        |‚d }~wt          $ r}t          d|› �¦  «        |‚d }~ww xY w|j        dk    r!‰j        j	        }t          d	|› d
|› �¦  «        ‚|j        dk    r't          d|j        › d|j
        d d…         › �¦  «        ‚|                     ¦   «         }|                     d¦  «        x}rt          d|› �¦  «        ‚|                     d¦  «        pi                      d¦  «        pd}	||	fS )NrR  rþ   rT  rU  r`  ra  rb  rW  rX  rY  r   rZ  r[  r\  r]  r^  r_  r  rk   )rO  r  rc  Úpostrj  rd  rô   r  r¿   ræ   rg   rV  r  )rá   rG  rk  r  r  rn  rÄ   r�   rl  r  rC  rE  rÊ   rÿ   s             €€€€rq   Ú_chatz(RAGService._invoke_ollama.<locals>._chatÊ  s?  ø€ Ø×/Ò/Ø K¸9ð 0ñ ô ˆGðMÝ”\¨'Ð2Ñ2Ô2ð M°fØ%Ÿ{š{¨dÐ+=Ð+=Ð+=ÀG˜{ÑLÔL�HðMð Mð Mñ Mô Mð Mð Mð Mð Mð Mð Møøøð Mð Mð Mð MøøåÔ)ð ð ð Ý"ØB¨gÐBÐB¸DÐBÐBñô àðøøøøõ ð Mð Mð MÝ"Ð#B¸SÐ#BÐ#BÑCÔCÈÐLøøøøðMøøøð Ô# sÒ*Ð*Ø!œ]Ô7�
Ý"ð> Zð >ð >Ø1;ð>ð >ñô ð ð Ô# sÒ*Ð*Ý"ØY¨HÔ,@ÐYÐYÀHÄMÐRVÐSVÐRVÔDWÐYÐYñô ð ð —=’=‘?”?ˆDØ—h’h˜wÑ'Ô'Ð'ˆsð ;Ý"Ð#9°CÐ#9Ð#9Ñ:Ô:Ð:Ø—x’x 	Ñ*Ô*Ð0¨b×5Ò5°iÑ@Ô@ÐFÀBˆGØ˜�=Ð sF   ›A# °AÁA# ÁAÁA# ÁAÁA# Á#B-Á2BÂB-ÂB(Â(B-)rG  rˆ   Ti   FÚdone_reasonÚlengthz,Ollama returned an empty reply (num_predict=z may be too low for z*; try raising OLLAMA_NUM_PREDICT_THINKING))rá   rF  rG  ru   ri   rq  )rD  rl   r<  r¿   r=  r  rd  ræ   )rÊ   rE  rá   rB  rA  rt  r�   r  Úretry_predictrC  rÿ   s   ``       @@rq   ró   zRAGService._invoke_ollamaÆ  sS  øøøø€ à(,×(<Ò(<¸[Ñ(IÔ(IÑ%ˆ�˜ ð	!ð 	!ð 	!ð 	!ð 	!ð 	!ð 	!ð 	!ð 	!ð> ˜˜g°Ð7Ñ7Ô7‰ˆˆgà�}Š}‰Œð 	JØð JÝ # G¨a¡K°´Ô1ZÐ]^Ñ1^Ñ _Ô _�Ø %  m¸tÐ DÑ DÔ D‘��g�gà % ¥c¨'°3Ñ&7Ô&7À5Ð IÑ IÔ I‘��gà�}Š}‰Œð 	 4§8¢8¨MÑ#:Ô#:¸hÒ#FÐ#FÝðZ¸wð Zð ZØ”=Ô-ðZð Zð Zñô ð ð �}Š}‰ŒÐrs   Úintentc                óÖ   — t                                |t          ¦  «        }|                      |                     |¬¦  «        | j        j        ¬¦  «        }t          ||dk    ¬¦  «        S )uO   Ollama reply for a single detected intent â€” no chat history (avoids mix-ups).©r„   rñ   rU   r™   )Ú_INTENT_PROMPTSr  r   ró   Úformatr¿   Ú!ollama_num_predict_conversationalr±   )rÊ   r„   rx  ÚtemplateÚraws        rq   Ú_intent_answerzRAGService._intent_answerù  sc   € å"×&Ò& v­~Ñ>Ô>ˆØ×!Ò!Ø�OŠO XˆOÑ.Ô.ØœÔGð "ñ 
ô 
ˆõ ˜S°¸5²ÐBÑBÔBÐBrs   c                óŒ   — |                       t          j        |¬¦  «        | j        j        ¬¦  «        }t          |d¬¦  «        S )Nrz  rñ   Fr™   )ró   r   r|  r¿   r}  r±   )rÊ   r„   r  s      rq   Ú_no_data_answerzRAGService._no_data_answer  sJ   € Ø×!Ò!ÝÔ!¨8Ð4Ñ4Ô4ØœÔGð "ñ 
ô 
ˆõ ˜S°Ð6Ñ6Ô6Ð6rs   Fr™   Úanswer_textr  úlist[Citation]Út0ÚfloatÚmoderš   r   c          	     óz  — ddl m} |dv r|pd                     ¦   «         }nt          ||¬¦  «        }t	          t          j        ¦   «         |z
  dz  ¦  «        }	t          j        d„ |D ¦   «         ¦  «        }
| 	                    |||
|	|¦  «        }|  
                    |||¦  «         t          |||||d d ¬¦  «        S )	Nr   )Údatabase)Ú
calculatorÚpdf_overviewrk   r™   iè  c                ó6   — g | ]}|                      ¦   «         ‘ŒS r´   )Ú
model_dump)rŸ   Úcs     rq   r/  z/RAGService._finish_response.<locals>.<listcomp>  s    € Ð$GÐ$GÐ$G¸ Q§\¢\¡^¤^Ð$GÐ$GÐ$Grs   )r&  r  r·   Úlog_idr‡  Ú
pdf_job_idÚpdf_summary)Úappr‰  rl   r±   rF  ÚtimeÚ	monotonicrV  ÚdumpsÚ	log_queryr(  r   )rÊ   r„   rƒ  r  r…  r·   r‡  rš   r‰  Úduration_msÚcitations_jsonr�  s               rq   Ú_finish_responsezRAGService._finish_response	  sç   € ð 	!Ð Ð Ð Ð Ð àÐ1Ð1Ð1Ø&Ð,¨"×3Ò3Ñ5Ô5ˆKˆKå'¨À=ÐQÑQÔQˆKÝ�4œ>Ñ+Ô+¨bÑ0°DÑ8Ñ9Ô9ˆÝœÐ$GÐ$G¸YÐ$GÑ$GÔ$GÑHÔHˆØ×#Ò# H¨k¸>È;ÐXbÑcÔcˆà�Š�z 8¨[Ñ9Ô9Ð9åØØØ!ØØØØð
ñ 
ô 
ð 	
rs   c           
     ó  — t          j        ¦   «         }|                     ¦   «         }t          |¦  «        }|dk    r)t	          |¦  «        }|                      ||g ||d¦  «        S t          |¦  «        }t          |oh|                     d¦  «        pS|                     d¦  «        p>|                     d¦  «        p)|                     d¦  «        p|                     d¦  «        ¦  «        }|�r«|dk    r2|  	                    ||¦  «        }|                      ||g ||d	d
¬¦  «        S t          ||¦  «        }|re|                      ||g ||d¦  «        }	|                     d¦  «        |	_        |                     d¦  «        pi                      d¦  «        |	_        |	S t          |¦  «        rtt          |¦  «        }|                      ||g ||d¦  «        }	|                     d¦  «        |	_        |                     d¦  «        pi                      d¦  «        |	_        |	S t          |¦  «        }
|                      |¦  «        }t#          j        |
¬¦  «        dz   |z   t'          j        |¬¦  «        z   }|                      |t+          d| j        j        ¦  «        ¬¦  «        }t0                               |pd                     ¦   «         ¦  «        s.t4                               |pd                     ¦   «         ¦  «        r4|dz   }|                      |t+          d| j        j        ¦  «        ¬¦  «        }|                      ||g ||d¦  «        }	|                     d¦  «        |	_        |                     d¦  «        pi                      d¦  «        |	_        |	S |t6          v r6|  	                    ||¦  «        }|                      ||g ||d	|dk    ¬¦  «        S t9          |¦  «        }|                      ||¦  «        }|rÄd|› �g}g }|r0|                      |¦  «        \  }}|                     d|› �¦  «         d                      |¦  «        }|                      |¦  «        }tC          j        |¬¦  «        dz   |z   t'          j        |¬¦  «        z   }|                      |¦  «        }|                      |||||d¦  «        S |s/|  "                    |¦  «        }|                      ||g ||d	¦  «        S |                      |¦  «        \  }}|                      |¦  «        }tC          j        |¬¦  «        dz   |z   t'          j        |¬¦  «        z   }|                      |¦  «        }|                      |||||d¦  «        S )NrŠ   rŠ  ÚrowsÚcalculationÚdocument_textÚtext_previewÚstatement_totalsrU   ÚconversationalTr™   r‹  Újob_idÚsummary)Úcontextr¥   rz  i  rñ   rk   u¥   

Rewrite your answer in natural sentences from the PDF text. Do not say Loadedâ€¦, do not start with the filename, and do not use 'Key balances' / 'Ratios:' labels.Úpdfz$Structured results (authoritative):
zRelated notes:
Úrag)#r“  r”  rl   r˜   Úcalc_expressionr™  r   ru   r  r€  r   r�  r‘  r   r   r   r%  r   r|  r   ró   r<  r¿   rè   Ú_CANNED_PDF_REPLY_REr’   Ú_LOADED_ACK_REr{  r   r7  r  rª   r«   r   r‚  )rÊ   r„   r·   r…  rx  rƒ  Úpdf_jobÚhas_pdfÚdirectÚrespÚpdf_contextÚhistoryrE  Úretry_promptÚ
structuredÚrelevantÚcontext_partsr  Úrag_contextr£  s                       rq   ÚchatzRAGService.chat*  s  € ÝŒ^ÑÔˆØ—>’>Ñ#Ô#ˆÝ Ñ)Ô)ˆð �VÒÐÝ)¨(Ñ3Ô3ˆKØ×(Ò(ØØØØØØñô ð õ " *Ñ-Ô-ˆÝØð à—’˜FÑ#Ô#ð 3Ø—;’;˜}Ñ-Ô-ð3à—;’;˜Ñ/Ô/ð3ð —;’;˜~Ñ.Ô.ð3ð —;’;Ð1Ñ2Ô2ñ	
ô 	
ˆð ñ <	Ø˜ŠˆØ"×1Ò1°(¸FÑCÔC�Ø×,Ò,ØØØØØØ$Ø"&ð -ñ ô ð õ 6°g¸xÑHÔHˆFØð Ø×,Ò,Ø˜f b¨"¨j¸.ñô �ð #*§+¢+¨hÑ"7Ô"7�”Ø$+§K¢K°Ñ$>Ô$>Ð$DÀ"×#IÒ#IÈ)Ñ#TÔ#T�Ô Ø�å'¨Ñ1Ô1ð Ý.¨wÑ7Ô7�Ø×,Ò,Ø˜k¨2¨r°:¸~ñô �ð #*§+¢+¨hÑ"7Ô"7�”Ø$+§K¢K°Ñ$>Ô$>Ð$DÀ"×#IÒ#IÈ)Ñ#TÔ#T�Ô Ø�å,¨WÑ5Ô5ˆKØ×)Ò)¨*Ñ5Ô5ˆGå!Ô(°Ð=Ñ=Ô=Øñàñõ Ô$¨hÐ7Ñ7Ô7ñ8ð ð ×-Ò-ØÝ  T¤]Ô%EÑFÔFð .ñ ô ˆKõ $×*Ò*¨KÐ,=¸2×+DÒ+DÑ+FÔ+FÑGÔGð Í>×K`ÒK`ØÐ" ×)Ò)Ñ+Ô+ñLô Lð ð ðHñHð ð #×1Ò1Ø Ý # C¨¬Ô)IÑ JÔ Jð 2ñ ô �ð ×(Ò(¨°;ÀÀBÈ
ÐTYÑZÔZˆDØ%Ÿkšk¨(Ñ3Ô3ˆDŒOØ '§¢¨MÑ :Ô :Ð @¸b×EÒEÀiÑPÔPˆDÔØˆKð •_Ð$Ð$Ø×-Ò-¨h¸Ñ?Ô?ˆKØ×(Ò(ØØØØØØ Ø%¨šð )ñ ô ð õ *¨(Ñ3Ô3ˆ
Ø—>’> (¨JÑ7Ô7ˆàð 	bØQÀZÐQÐQÐRˆMØ(*ˆIØð GØ)-×)=Ò)=¸hÑ)GÔ)GÑ&�˜YØ×$Ò$Ð%E¸Ð%EÐ%EÑFÔFÐFØ—k’k -Ñ0Ô0ˆGØ×)Ò)¨*Ñ5Ô5ˆGåÔ$¨WÐ5Ñ5Ô5Øñàñõ Ô$¨hÐ7Ñ7Ô7ñ8ð ð ×-Ò-¨fÑ5Ô5ˆKØ×(Ò(¨°;À	È2ÈzÐ[`ÑaÔaÐaàð 	fØ×.Ò.¨xÑ8Ô8ˆKØ×(Ò(¨°;ÀÀBÈ
ÐTdÑeÔeÐeà!×1Ò1°(Ñ;Ô;Ñˆ�Ø×%Ò% jÑ1Ô1ˆåÔ ¨Ð1Ñ1Ô1Øñàñõ Ô ¨(Ð3Ñ3Ô3ñ4ð 	ð ×)Ò)¨&Ñ1Ô1ˆØ×$Ò$ X¨{¸IÀrÈ:ÐW\Ñ]Ô]Ð]rs   )r¿   r
   )ri   r   )ri   r	   )ri   rÙ   )ri   r¹   )ri   rö   )ri   ru   )ri   r  )r·   r¸   ri   rh   )r·   r¸   r„   rh   r&  rh   ri   r¹   rž   )r„   rh   r·   r¸   )rá   rö   ri   r8  )rE  rh   rá   rF  rG  ru   ri   rH  )rE  rh   rá   rö   ri   rP  )rE  rh   rá   rö   ri   rh   )r„   rh   rx  rh   ri   rh   ©r„   rh   ri   rh   )r„   rh   rƒ  rh   r  r„  r…  r†  r·   r¸   r‡  rh   rš   ru   ri   r   )r„   rh   r·   r¸   ri   r   )Ú__name__Ú
__module__Ú__qualname__rË   ÚpropertyrÎ   rØ   rî   rõ   rò   rü   r  r  r%  r(  r7  rD  rO  ro  ró   r€  r‚  r™  r´  r´   rs   rq   r¾   r¾     s  € € € € € ð0ð 0ð 0ð 0ð ð ð  ð  ñ „Xð ð!ð !ð !ð !ðð ð ð ð"ð ð ð ðð ð ð ð/ð /ð /ð /ðð ð ð ð5ð 5ð 5ð 5ð6
)ð 
)ð 
)ð 
)ð@ð @ð @ð @ð
Zð Zð Zð Zð Zð	-ð 	-ð 	-ð 	-ð
ð 
ð 
ð 
ð" 9=ð)Ið )Ið )Ið )Ið )Ið )IðV HLð 1ð 1ð 1ð 1ð 1ð 1ðfCð Cð Cð Cð7ð 7ð 7ð 7ð  $ð
ð 
ð 
ð 
ð 
ð 
ðBK^ð K^ð K^ð K^ð K^ð K^ð K^rs   r¾   c                 ó8   — t          t          ¦   «         ¦  «        S rž   )r¾   r   r´   rs   rq   Úget_rag_servicer»  ¸  s   € å•l‘n”nÑ%Ô%Ð%rs   )rg   rh   ri   rh   )rt   rh   ri   ru   rµ  )rg   rh   rš   ru   ri   rh   )r·   r¸   ri   r¹   )ri   r¾   )IÚ__doc__Ú
__future__r   r�   rV  rn   r“  Úcollectionsr   r   Úcollections.abcr   Ú	functoolsr   r  Úlangchain_community.embeddingsr   Ú langchain_community.vectorstoresr	   Ú
app.configr
   r   Úapp.models.schemasr   r   Úapp.rag.promptsr   r   r   r   r   r   r   r   r   r   Úapp.rag.calculatorr   r¦  r   Úapp.rag.structuredr   Úapp.pdf.calcr   r   r   r   Úapp.pdf.storer   r}   r�   rŽ   r�   Úcompiler‘   r”   r¦   r–   r—   r©   r¬   r§  r¨  rr   rƒ   r˜   r±   r¶   Ú__annotations__r¼   r{  r¾   r»  r´   rs   rq   ú<module>rÌ     s<  ðØ ;Ð ;Ð ;à "Ð "Ð "Ð "Ð "Ð "à €€€Ø €€€Ø 	€	€	€	Ø €€€Ø *Ð *Ð *Ð *Ð *Ð *Ð *Ð *Ø $Ð $Ð $Ð $Ð $Ð $Ø Ð Ð Ð Ð Ð à €€€Ø @Ð @Ð @Ð @Ð @Ð @Ø 3Ð 3Ð 3Ð 3Ð 3Ð 3à -Ð -Ð -Ð -Ð -Ð -Ð -Ð -Ø 5Ð 5Ð 5Ð 5Ð 5Ð 5Ð 5Ð 5ðð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð <Ð ;Ð ;Ð ;Ð ;Ð ;Ø +Ð +Ð +Ð +Ð +Ð +Ø 3Ð 3Ð 3Ð 3Ð 3Ð 3Ø +Ð +Ð +Ð +Ð +Ð +Ø eÐ eÐ eÐ eÐ eÐ eÐ eÐ eÐ eÐ eØ )Ð )Ð )Ð )Ð )Ð )ðð ð €ð :Ð9Ð9€Ø4Ð4Ð4€
ðð ð €ð$ ˆ2Œ:ðñ
ô 
€ð �"”*ð
ñô €ð ˆrŒzðð „Mñ
ô 
€ð ˆbŒjðð „Mñô €ð €B„JÐ*Ñ+Ô+Ø€B„JÐ,Ñ-Ô-Ø€B„Jð  Rñ  Sô  SØ€B„JÐQÑRÔRð	€ð ˆbŒjØUñô €ð
 "�r”zð!ñô Ð ð �”ØDñô €ð
ð ð ð ð
ð 
ð 
ð 
ð'ð 'ð 'ð 'ðT 7<ð Tð Tð Tð Tð Tð Tð> 7B°kÐBYÐBYÑ6ZÔ6ZÐ Ð ZÐ ZÐ ZÑ Zð+ð +ð +ð +ð  ØØØØØðð €ðt^ð t^ð t^ð t^ð t^ñ t^ô t^ð t^ðn ð&ð &ð &ñ „ð&ð &ð &rs   