1414from dotenv import load_dotenv
1515from exasol .ai .mcp .server .load_prompt import load_prompt
1616from exasol .ai .mcp .server .server_settings import ExaDbResult
17+ import json
1718from langchain_core .prompts import ChatPromptTemplate
1819from langchain_openai import ChatOpenAI
1920from langgraph .graph import StateGraph , START , END
2021import os
22+ import pprint
2123from pydantic import BaseModel , Field
2224import pyexasol
2325from pyexasol import ExaError
26+ import re
2427from sqlglot import exp , parse_one
2528from sqlglot .errors import ParseError
2629import sys
2730from typing_extensions import TypedDict
2831
32+ import ssl
2933
3034############################################################################
3135## Get the user password stored encrypted on the desktop file system ##
@@ -141,6 +145,7 @@ def t2s_database_schema(db_schema: str, env: dict) -> str:
141145
142146 return schema_metadata
143147
148+
144149##################################################################
145150## Check if human question relates to requested database schema ##
146151##################################################################
@@ -221,7 +226,8 @@ def t2s_human_language_to_sql(state: GraphState):
221226 system_prompt = load_prompt (db_schema = db_schema , schema = schema )
222227
223228 ##
224- ## Check VectorDB for a similar question and SQL Statement
229+ ## Check VectorDB for a similar question and SQL Statement,
230+ ## retrieve a threshold for similarity from the .env file
225231 ##
226232
227233 try :
@@ -328,7 +334,17 @@ def t2s_execute_query(state: GraphState):
328334 try :
329335 with pyexasol .connect (dsn = env ['dsn' ], user = env ['db_user' ], password = env ['db_password' ], schema = state ['db_schema' ]) as c :
330336 rows = c .execute (state ['sql_statement' ]).fetchall ()
331- #rows = c.export_to_pandas(state['sql_statement'])
337+
338+ cols = c .meta .sql_columns (state ['sql_statement' ])
339+
340+ col_names = tuple (cols .keys ())
341+
342+ rows .insert (0 , col_names )
343+ rslt = rows
344+
345+ print (f"#### End of SQL Execution-COLS { cols } " , file = sys .stderr )
346+ print (f"#### End of SQL Execution-ROWS { rows } " , file = sys .stderr )
347+ print (f"#### End of SQL Execution-TABLE { rslt } " , file = sys .stderr )
332348
333349 state ['query_result' ] = str (ExaDbResult (rows ))
334350 state ['query_num_rows' ] = c .last_statement ().rowcount ()
@@ -398,14 +414,51 @@ class DisplayResult(BaseModel):
398414 description = "The result set converted into a nice and shiny table in MARKDOWN syntax."
399415 )
400416
417+
401418def t2s_show_answer (state : GraphState ):
402419
403420 env = get_environment ()
404421
405- state ['display_result' ] = state ['query_result' ]
422+ result = re .search (r"(\[.*\])" , state ['query_result' ])
423+ result_set = result .group (0 )
424+
425+ system_prompt = f"""
426+ You are a helpful assistant formatting datasets. You will use Markdown syntax.
427+ Print the final result.
428+ """
429+
430+ question = f"""Transform the dataset below into a table in markdown syntax:
431+
432+ { result_set }
433+
434+ """
435+
436+ print (f"Show-Result-System-Prompt :: { system_prompt } \n { question } " , file = sys .stderr )
437+
438+ #user_prompt = "" # Question: " + state['query_result'"]
439+
440+ llm = ChatOpenAI (model_name = env ["llm_server_sql_transform" ],
441+ temperature = 0.0 ,
442+ openai_api_base = env ["llm_server_url" ],
443+ openai_api_key = env ["llm_server_api_token" ]).with_structured_output (DisplayResult )
444+
445+
446+
447+ t2s_prompt = ChatPromptTemplate .from_messages (
448+ [
449+ ( "system" , system_prompt ),
450+ ( "user" , "Question: {question}" ),
451+ ]
452+ )
453+
454+ render_process = t2s_prompt | llm
455+ result = render_process .invoke ({"question" : question })
456+ state ["display_result" ] = str (result .display_result )
457+
458+
406459
407460 print (f" " , file = sys .stderr )
408- print (f"Show-Answer :: { state [ 'query_result' ] } " , file = sys .stderr )
461+ print (f"Show-Answer :: { result_set } " , file = sys .stderr )
409462 print (f"Show-Answer-2 :: { state ['display_result' ]} " , file = sys .stderr )
410463 print (f" " , file = sys .stderr )
411464
@@ -546,6 +599,7 @@ async def start_t2s_process(state: GraphState):
546599
547600 workflow = StateGraph (GraphState )
548601
602+ workflow .add_edge (START , "check_relevance" )
549603 workflow .add_node ("check_relevance" , t2s_check_relevance )
550604 workflow .add_node ("transform_into_sql" , t2s_human_language_to_sql )
551605 workflow .add_node ("info_unable_query_type" , t2s_info_unable_query_type )
@@ -558,8 +612,6 @@ async def start_t2s_process(state: GraphState):
558612 workflow .add_node ("info_unable_create_sql" , t2s_info_unable_create_sql )
559613 workflow .add_node ("check_sql_valid" , t2s_check_sql_valid )
560614
561- workflow .add_edge (START , "check_relevance" )
562-
563615 workflow .add_conditional_edges (
564616 "check_relevance" ,
565617 t2s_relevance_router ,
@@ -568,17 +620,6 @@ async def start_t2s_process(state: GraphState):
568620 "NO" : "info_query_not_relevant" ,
569621 },
570622 )
571- workflow .add_edge ("execute_query" , "check_sql_valid" )
572-
573- workflow .add_conditional_edges (
574- "check_sql_valid" ,
575- t2s_sql_valid_router ,
576- {
577- "YES" : "show_answer" ,
578- "NO" : "check_max_tries"
579- }
580- )
581-
582623
583624 workflow .add_conditional_edges (
584625 "check_max_tries" ,
@@ -590,6 +631,8 @@ async def start_t2s_process(state: GraphState):
590631
591632 )
592633
634+ workflow .add_edge ("transform_into_sql" , "check_sql_is_allowed" )
635+
593636 workflow .add_conditional_edges (
594637 "check_sql_is_allowed" ,
595638 t2s_check_sql_router ,
@@ -599,15 +642,24 @@ async def start_t2s_process(state: GraphState):
599642 }
600643 )
601644
602- workflow .add_edge ("transform_into_sql" , "check_sql_is_allowed" )
603- #workflow.add_edge("transform_into_sql", "execute_query")
645+ workflow .add_edge ("execute_query" , "check_sql_valid" )
646+
647+ workflow .add_conditional_edges (
648+ "check_sql_valid" ,
649+ t2s_sql_valid_router ,
650+ {
651+ "YES" : "show_answer" ,
652+ "NO" : "check_max_tries"
653+ }
654+ )
655+
656+ workflow .add_edge ("show_answer" , END )
657+
604658 workflow .add_edge ("correct_query" , "transform_into_sql" )
605659 workflow .add_edge ("info_query_not_relevant" , END )
606660 workflow .add_edge ("info_unable_create_sql" , END )
607661
608- ## to be changed
609- # workflow.add_edge("execute_query", "show_answer")
610- workflow .add_edge ("show_answer" , END )
662+
611663
612664 t2s_process = workflow .compile ()
613665
0 commit comments