§
    éƒtjÅ  ã                  ó†   — d Z ddlm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ZdZd$d„Zddddœd%d„Zddœd&d!„Zd'd#„ZdS )(uO   LLM reasoning over retrieved / structured evidence â€” never return raw chunks.é    )ÚannotationsN)ÚAnyÚCallable)Úget_settings)ÚStructuredInsightuL  You are {agent_name}, an AI financial analyst.

The user asked a document-related question. Below is structured evidence from their uploaded statement.
Write a concise, natural answer (2â€“5 short sentences). Lead with the direct answer.
Use only the evidence â€” never invent merchants, amounts, or dates.
If evidence is thin, say what you can and cannot tell from the statement.
Do not paste raw tables or OCR. Do not mention extraction, chunks, RAG, vectors, or indexing gaps.
Sound like a helpful colleague.

{name_line}
User question: {question}

Evidence (JSON):
{evidence}

Answer:uÏ  You are {agent_name}, an AI financial analyst helping the user improve their money habits.

Using ONLY the evidence from their uploaded statement, give personalized, actionable advice.
Requirements:
- 3â€“6 short sentences, conversational tone
- Cite specific merchants or amounts from the evidence as proof
- Mention concentration (where money goes), one clear cut opportunity, and one concrete next step
- Enrich with insights already computed (average, highest spend, frequency, share of total) when present
- If evidence includes focus_merchant, center the advice on that merchant â€” cite its total, payment count, and share. Never claim that merchant is missing when focus_merchant is present.
- Never invent figures. Never give tax, legal, or investment product advice.
- Never mention extraction, incomplete indexing, chunks, RAG, or internal systems.
- Do not dump a full transaction list.

{name_line}
User question: {question}

Evidence (JSON):
{evidence}

Advice:Ú	user_nameú
str | NoneÚreturnÚstrc                ó   — | rd| › d�S dS )NzThe user's name is z . You may use it once naturally.Ú © )r   s    ú+/var/www/html/CA-Chatbot/app/saas/reason.pyÚ
_name_liner   3   s!   € Øð QØP YÐPÐPÐPÐPØˆ2ó    F)r   ÚanalysisÚon_tokenÚ
agent_nameÚquestionÚevidenceúdict[str, Any]Úinvoke_ollamaúCallable[..., str]r   Úboolr   úCallable[[str], None] | Nonec           
     óþ  — |rt           nt          }|                     | pdt          |¦  «        |pd                     ¦   «         t          j        |dd¬¦  «        d d…         ¬¦  «        }t          |rdnd	t          ¦   «         j	        ¦  «        }		 |r´g }
t          |d
d ¦  «        }|rt          |dd ¦  «        nd }t          |¦  «        rF |||	¬¦  «        D ]"}|
                     |¦  «          ||¦  «         Œ#d                     |
¦  «        }nD |||	¬¦  «        }|r'|r%t          j        d|¦  «        D ]}|r ||¦  «         Œn |||	¬¦  «        }n# t           $ r Y d S w xY w|pd                     ¦   «         }|pd S )NÚAlexr   Fé   )Úensure_asciiÚindentip  )r   Ú	name_liner   r   i  éÜ   Ú__self__Ústream_ollama)Únum_predictz(\s+))ÚANALYSIS_PROMPTÚSYNTHESIS_PROMPTÚformatr   ÚstripÚjsonÚdumpsÚmaxr   Ú!ollama_num_predict_conversationalÚgetattrÚcallableÚappendÚjoinÚreÚsplitÚ	Exception)r   r   r   r   r   r   r   ÚtemplateÚpromptÚpredictÚpartsÚstreamÚ	stream_fnÚchunkÚrawÚpieceÚtexts                    r   Úsynthesize_from_evidencer?   9   sÞ  € ð #+Ð@�ˆÕ0@€HØ�_Š_ØÐ' Ý˜YÑ'Ô'Ø�.˜b×'Ò'Ñ)Ô)Ý”˜H°5ÀÐCÑCÔCÀEÀTÀEÔJð	 ñ ô €Fõ ØÐ ˆˆ˜SÝ‰ŒÔ8ñô €GðØð 	=Ø!ˆEå˜]¨J¸Ñ=Ô=ˆFØBHÐR� ¨¸Ñ>Ô>Ð>ÈdˆIÝ˜	Ñ"Ô"ð 
,Ø&˜Y v¸7ÐCÑCÔCð $ð $�EØ—L’L Ñ'Ô'Ð'Ø�H˜U‘O”O�O�OØ—g’g˜e‘n”n��à#�m F¸Ð@Ñ@Ô@�Øð ,˜8ð ,Ý!#¤¨(°CÑ!8Ô!8ð ,ð ,˜Ø ð ,Ø$˜H U™OœO˜Oøøà�- °GÐ<Ñ<Ô<ˆCøøÝð ð ð ØˆtˆtðøøøàˆI�2×ÒÑÔ€DØˆ<�4Ðs   ÂCE Å
E"Å!E"é   )Úmax_txnsÚinsightr   rA   Úintc               óR  — | j         | j        | j        d„ | j        pg dd…         D ¦   «         t	          | j        pg ¦  «        dd…         dœ}| j        rd„ | j        d|…         D ¦   «         |d<   | j        r0| j        j        r$| j        j	        | j        j        dd…         dœ|d	<   |S )
u7   Compact facts for LLM synthesis â€” not raw chunk text.c                ó8   — g | ]}|j         |j        |j        d œ‘ŒS )©ÚlabelÚvalueÚhintrF   )Ú.0Úms     r   ú
<listcomp>z,insight_evidence_payload.<locals>.<listcomp>m   s8   € ð 
ð 
ð 
àð ”g¨¬¸¼Ð@Ð@ð
ð 
ð 
r   Né
   é   )ÚheadlineÚsummaryÚintentÚmetricsÚ
highlightsc                óD   — g | ]}|j         |j        |j        |j        d œ‘ŒS )©ÚdateÚdescriptionÚamountÚ	directionrU   )rJ   Úts     r   rL   z,insight_evidence_payload.<locals>.<listcomp>t   sE   € ð &
ð &
ð &
ð ð œØ œ}Øœ(Øœ[ð	ð ð&
ð &
ð &
r   Úsample_payments)ÚheadersÚrowsÚtable)
rO   rP   rQ   rR   ÚlistrS   Útransactionsr^   r]   r\   )rB   rA   Úpayloads      r   Úinsight_evidence_payloadrb   g   sò   € ð Ô$Ø”?Ø”.ð
ð 
à”oÐ+¨¨S¨b¨SÔ1ð
ñ 
ô 
õ ˜7Ô-Ð3°Ñ4Ô4°R°a°RÔ8ð	ð 	€Gð Ôð 	
ð&
ð &
ð Ô)¨)¨8¨)Ô4ð&
ñ &
ô &
ˆÐ!Ñ"ð „}ð 
˜œÔ+ð 
à”}Ô,Ø”MÔ& s¨ sÔ+ð
ð 
ˆ�Ñð €Nr   r>   c                óz   — | s| S g d¢}| }|D ]\  }}t          j        |||¦  «        }Œ|                     ¦   «         S )z;Hide backend extraction / indexing language from end users.))z#(?i)extraction\s+incomplete[^.]*\.?r   )z#(?i)incomplete\s+extraction[^.]*\.?r   )z,(?i)only\s+\d+\s+of\s+\d+\s+payments[^.]*\.?r   )z (?i)could\s+only\s+index[^.]*\.?r   )z-(?i)\d+\s+dated\s+outflows?\s+indexed[^.]*\.?r   )z(?i)\bindexed\s+outflows?\bÚpayments)z$(?i)prefer\s+header\s+totals[^.]*\.?r   )z@(?i)line\s+lists?\s+below\s+are\s+not\s+the\s+full\s+set[^.]*\.?r   )z*(?i)\b(?:vector|embedding|chunk|OCR|RAG)\br   )z	[ \t]{2,}Ú )z\n{3,}z

)r2   Úsubr)   )r>   ÚpatternsÚoutÚpatÚrepls        r   Úscrub_internal_user_textrk   …   s]   € àð Øˆðð ð €Hð €CØð %ð %‰	ˆˆTÝŒf�S˜$ Ñ$Ô$ˆˆØ�9Š9‰;Œ;Ðr   )r   r	   r
   r   )r   r   r   r   r   r   r   r   r   r	   r   r   r   r   r
   r	   )rB   r   rA   rC   r
   r   )r>   r   r
   r   )Ú__doc__Ú
__future__r   r*   r2   Útypingr   r   Ú
app.configr   Úapp.models.schemasr   r'   r&   r   r?   rb   rk   r   r   r   ú<module>rq      sû   ðØ UÐ Uà "Ð "Ð "Ð "Ð "Ð "à €€€Ø 	€	€	€	Ø  Ð  Ð  Ð  Ð  Ð  Ð  Ð  à #Ð #Ð #Ð #Ð #Ð #Ø 0Ð 0Ð 0Ð 0Ð 0Ð 0ðÐ ð"€ð,ð ð ð ð !ØØ-1ð+ð +ð +ð +ð +ð +ð\ MOð ð ð ð ð ð ð<ð ð ð ð ð r   