
    i&              	          S SK JrJrJr  S SKJrJr  S SKJr  S SK	J
r
JrJrJr  S SKJr  S SKJr  S SKJr  S SKJr  S S	KJrJr  S S
KJrJr  S SKJr  S SKrS SKrS SK J!r!  \" SSSS9r"\RF                  " SSSSSSS9r$\!" S5      r%Sr&\" 5       r'\" \'5      4S\4S jjr(Sq)Sq*Sq+Sq,S r-S r.S r/S  r0S!\1S"\\1   4S# jr2S$\1S%\3S"\
\\1\4      4S& jr4 " S' S(\5      r5 " S) S*\5      r6\"Ro                  S+5      S, 5       r8\"Ro                  S-5      \" \(5      4S.\14S/ jj5       r9\"Ro                  S05      \" \(5      4S1\1S.\14S2 jj5       r:\"Rw                  S3\6S49\" \(5      4S5\5S.\14S6 jj5       r<\=S7:X  a  S SK>r>\>R~                  " S8S9S:S;S<9  gg)=    )FastAPIHTTPExceptionDepends)
HTTPBearerHTTPAuthorizationCredentials)	BaseModel)ListDictAnyOptional)
ChatOllama)SQLDatabase)Chroma)HuggingFaceEmbeddings)HumanMessageSystemMessage)create_enginetext)URLN)Pathz*Agriculture Chat-to-SQL API (Local Ollama)z7Text-to-SQL using local llama3.2:3b-instruct via Ollamaz0.1.1)titledescriptionversionzpostgresql+psycopg2postgreszgQube1_#@96740z139.59.87.82i8  four_s_india)
drivernameusernamepasswordhostportdatabasezschema_chunks.jsonz"testing-2026-kolkata-llama-api-keycredentialsc                 V    U R                   [        :w  a
  [        SSS9eU R                   $ )Ni  zInvalid API Keystatus_codedetail)r"   API_KEYr   )r"   s    $/var/www/html/dynamic-report/main.pyverify_api_keyr)   -   s*    ')4EFF"""    c                  8    [         c  [        [        SS9q [         $ )NT)pool_pre_ping)enginer   db_url r*   r(   
get_enginer0   ;   s    ~vT:Mr*   c                  B    [         c  [        [        5       5      q [         $ N)dbr   r0   r/   r*   r(   get_dbr4   A   s    	z&Ir*   c                     [         c  [        R                  5       (       d  [        S5      e[	        [        SSS9 n [
        R                  " U 5      nS S S 5        W Vs/ s H  o"S   PM	     nnU Vs/ s H  o"R                  S0 5      PM     nn[        SS9n[        R                  " UUUS	S
9q [         $ ! , (       d  f       Ni= fs  snf s  snf )Nu2   schema_chunks.json missing – run ingestion firstrzutf-8)encodingr   metadataz&sentence-transformers/all-MiniLM-L6-v2)
model_nameagri_schema_local)texts	embedding	metadatascollection_name)vectorstoreSCHEMA_CHUNKS_PATHexistsRuntimeErroropenjsonloadgetr   r   
from_texts)fchunkscr;   r=   
embeddingss         r(   get_vectorstorerL   G   s    !((**STT$cG<YYq\F = %++Fq6F+4:;FqUU:r*F	;*6^_
'' /	
  =< ,;s   B5C2C5
Cc                  6    [         c  [        SSSSSS9q [         $ )Nzllama3.2:3b-instruct-q4_0g        i   i   zhttp://localhost:11434)modeltemperaturenum_ctxnum_predictbase_url)llmr   r/   r*   r(   get_llmrT   ]   s'    
{--
 Jr*   r   returnc                    U R                   " 5       n [        R                  " SU [        R                  [        R                  -  5      nU(       a  UR                  S5      R                  5       $ [        R                  " SU [        R                  [        R                  -  5      nU(       a  UR                  S5      R                  5       $ [        R                  " SU [        R                  [        R                  -  5      nU(       aW  UR                  S5      R                  5       nUR                  5       R                  S5      (       a  UR                  S5      S-   $ U R                  " 5       nU HM  nUR                  5       nUR                  5       R                  S5      (       d  M9  UR                  S5      S-   s  $    g )Nz```sql\s*(.*?)\s*```   z```\s*(SELECT\s+.*?)\s*```z(SELECT\s+.*?)(?:\n{2,}|$|;)SELECT;)
stripresearchDOTALL
IGNORECASEgroupupper
startswithrstrip
splitlines)r   matchsqllineslinestrippeds         r(   extract_sqlri   m   s>   ::<D II-tRYY5NOE{{1~##%% II3T299r}};TUE{{1~##%% II5tRYY=VWEkk!n""$99;!!(++::c?S(( OOE::<>>&&x00??3'#-- 
 r*   re   max_rowsc           
      R   [        5       R                  5        nUR                  [        U 5      5      n[	        UR                  5       5      n/ n[        U5       H/  u  pgXa:  a    O'UR                  [        [        XG5      5      5        M1     UsS S S 5        $ ! , (       d  f       g = fr2   )
r0   connectexecuter   listkeys	enumerateappenddictzip)re   rj   connresultcolumnsrowsirows           r(   run_sqlrz      sy    				4d3i(v{{}%'FA}KKS./0 (  
 		s   A5B
B&c                   4    \ rS rSr% \\S'   Sr\\   \S'   Sr	g)QueryRequest   question   rj   r/   N)
__name__
__module____qualname____firstlineno__str__annotations__rj   r   int__static_attributes__r/   r*   r(   r|   r|      s    M!Hhsm!r*   r|   c                       \ rS rSr% \\S'   Sr\\   \S'   Sr\\	\
\\4         \S'   Sr\\   \S'   Sr\\   \S'   Sr\\   \S'   S	rg)
QueryResponse   r~   Ngenerated_sqlrw   	row_countnatural_answererrorr/   )r   r   r   r   r   r   r   r   rw   r	   r
   r   r   r   r   r   r   r/   r*   r(   r   r      s[    M#'M8C='+/D(4S#X'
(/#Ix}#$(NHSM(E8C=r*   r   z/healthc                     #    SSS.$ 7f)Nokz ollama-llama3.2:3b-instruct-q4_0)statusrS   r/   r/   r*   r(   healthr      s     #EFFs   z/tables_c                 T   #    [        [        5       R                  5       5      nSU0$ 7f)Ntables)sortedr4   get_usable_table_names)r   r   s     r(   list_tablesr      s%     FH3356Ffs   &(z/table/{table_name}
table_namec                 F   #    [        5       R                  U /5      nXS.$ 7f)N)tableinfo)r4   get_table_info_no_throw)r   r   r   s      r(   get_table_infor      s"     8++ZL9D..s   !z/query)response_modelreqc           	      ,  #     [        5       R                  U R                  SS9nSR                  S U 5       5      nSnX4-  nSnSU SU R                   S	3n[	        5       R                  [        US
9[        US
9/5      nUR                  R                  5       n[        U5      n	U	(       d8  UR                  5       R                  S5      (       a  UR                  S5      S-   n	U	(       d  [        U R                  USS9$  [        XR                   5      n
[        U R                  U	U
['        U
5      S9$ ! ["         a+  n[        U R                  U	S[%        U5       3S9s S nA$ S nAff = f! ["         a  n[)        S[%        U5      S9eS nAff = f7f)N   )kz

c              3   8   #    U  H  oR                   v   M     g 7fr2   )page_content).0ds     r(   	<genexpr>ask.<locals>.<genexpr>   s     ;dnnds   u   

SPECIAL RULE FOR STATE: Column 'state' is character varying(255) → string/text. ALWAYS use quotes: state = 'West Bengal' or state = '4' (never state = 4 without quotes). Do NOT use numeric comparison without CAST or quotes.u  You are a strict PostgreSQL SQL generator.
Output ONLY the SQL query — nothing else. No explanation, no markdown, no code blocks, no text before or after the SQL.

STRICT RULES - YOU MUST FOLLOW:
- Use ONLY tables that appear EXACTLY in the schema context below.
- NEVER invent or use tables like 'farmer_csv_records', 'users_csv', or any name not listed.
- If no suitable table exists → output exactly: INSUFFICIENT SCHEMA
- For counting farmers → MUST use 'upload_farmer' or 'agri_users' tables.
- Column 'state' is string → always use quotes: 'West Bengal' or '4'
- Use COUNT(*) for row counts
- End every query with semicolon ;
- Never INSERT, UPDATE, DELETE, DROPzSchema context:
z

Question: z

SQL query:)contentrX   rY   z@Model did not produce valid SQL. Try rephrasing or check schema.)r~   r   r   zSQL execution failed: )r~   r   r   )r~   r   rw   r   i  r$   )rL   similarity_searchr~   joinrT   invoker   r   r   rZ   ri   r`   ra   rb   r   rz   rj   	Exceptionr   lenr   )r   r   docscontext
state_hintsystem_promptuser_promptresponse
raw_outputre   rw   exes                r(   askr      s    L< 223<<12E++;d;;D 	 	(	 
<<.  9##-0-%
 
 %%++-
 *% z'')44X>>##C(3.C )X 	3-D \\$i	
 	
  	 !.s2wi8 	  <CF;;<se   FC=E/ FD7 E/ 6F7
E, E'!E,"E/ &F'E,,E/ /
F9FFF__main__zmain:appz0.0.0.0iA  T)r   r    reload)@fastapir   r   r   fastapi.securityr   r   pydanticr   typingr	   r
   r   r   langchain_ollamar   langchain_community.utilitiesr    langchain_community.vectorstoresr   langchain_huggingfacer   langchain_core.messagesr   r   
sqlalchemyr   r   sqlalchemy.enginer   rD   r[   pathlibr   appcreater.   r@   r'   securityr)   r-   r3   r?   rS   r0   r4   rL   rT   r   ri   r   rz   r|   r   rF   r   r   r   postr   r   uvicornrunr/   r*   r(   <module>r      s   4 3 E  , , ' 5 3 7 ? * !  	 
6I 
$		
 ./ 
.<?Fx?P # < # 
	
,
 c hsm B	 	 	T#s(^(< 	"9 " I   G G &~6    	3:>3J /S /S /  / (=1*1.*A M<< M<C M< 2M<^ zKK
dC r*   