Soumik555 commited on
Commit
a7202b3
·
1 Parent(s): 8688d5e

single tooltip component

Browse files
controller.py CHANGED
@@ -402,7 +402,7 @@ def handle_out_of_range_float(value):
402
  instructions = """
403
 
404
  - Please ensure that each value is clearly visible, You may need to adjust the font size, rotate the labels, or use truncation to improve readability (if needed).
405
- - For multiple charts, arrange them in a grid format (2x2, 3x3, etc.)
406
  - Use colorblind-friendly palette
407
  - Read above instructions and follow them.
408
 
@@ -479,189 +479,6 @@ def groq_chart(csv_url: str, question: str):
479
 
480
 
481
 
482
- # def langchain_csv_chart(csv_url: str, question: str, chart_required: bool):
483
- # global current_langchain_chart_key_index, current_langchain_chart_lock
484
-
485
- # data = clean_data(csv_url)
486
-
487
- # for attempt in range(len(groq_api_keys)):
488
- # try:
489
- # with current_langchain_chart_lock:
490
- # api_key = groq_api_keys[current_langchain_chart_key_index]
491
- # current_key = current_langchain_chart_key_index
492
- # current_langchain_chart_key_index = (current_langchain_chart_key_index + 1) % len(groq_api_keys)
493
-
494
- # llm = ChatGroq(model=model_name, api_key=api_key)
495
- # tool = PythonAstREPLTool(locals={
496
- # "df": data,
497
- # "pd": pd,
498
- # "np": np,
499
- # "plt": plt,
500
- # "sns": sns,
501
- # "matplotlib": matplotlib,
502
- # "uuid": uuid
503
- # })
504
-
505
- # agent = create_pandas_dataframe_agent(
506
- # llm,
507
- # data,
508
- # agent_type="openai-tools",
509
- # verbose=True,
510
- # allow_dangerous_code=True,
511
- # extra_tools=[tool],
512
- # return_intermediate_steps=True
513
- # )
514
-
515
- # result = agent.invoke({"input": _prompt_generator(question, True)})
516
- # output = result.get("output", "")
517
-
518
- # # Verify chart file creation
519
- # chart_files = extract_chart_filenames(output)
520
- # if len(chart_files) > 0:
521
- # return chart_files
522
-
523
- # if attempt < len(groq_api_keys) - 1:
524
- # print(f"Langchain chart error (key {current_key}): {output}")
525
-
526
- # except Exception as e:
527
- # print(f"Langchain chart error (key {current_key}): {str(e)}")
528
-
529
- # return "Chart generation failed after all retries"
530
-
531
- # @app.post("/api/csv-chart")
532
- # async def csv_chart(request: dict, authorization: str = Header(None)):
533
- # # Authorization verification
534
- # if not authorization or not authorization.startswith("Bearer "):
535
- # raise HTTPException(status_code=401, detail="Authorization required")
536
-
537
- # token = authorization.split(" ")[1]
538
- # if token != os.getenv("AUTH_TOKEN"):
539
- # raise HTTPException(status_code=403, detail="Invalid credentials")
540
-
541
- # try:
542
- # query = request.get("query", "")
543
- # csv_url = unquote(request.get("csv_url", ""))
544
-
545
- # # Parallel processing with thread pool
546
- # if if_initial_chart_question(query):
547
- # chart_paths = await asyncio.to_thread(
548
- # langchain_csv_chart, csv_url, query, True
549
- # )
550
- # print(chart_paths)
551
-
552
- # if len(chart_paths) > 0:
553
- # return FileResponse(f"{image_file_path}/{chart_paths[0]}", media_type="image/png")
554
-
555
- # # Groq-based chart generation
556
- # groq_result = await asyncio.to_thread(groq_chart, csv_url, query)
557
- # print(f"Generated Chart: {groq_result}")
558
- # if groq_result != 'Chart not generated':
559
- # return FileResponse(groq_result, media_type="image/png")
560
-
561
-
562
- # # Fallback to Langchain
563
- # langchain_paths = await asyncio.to_thread(
564
- # langchain_csv_chart, csv_url, query, True
565
- # )
566
-
567
- # print (langchain_paths)
568
-
569
- # if len(langchain_paths) > 0:
570
- # return FileResponse(f"{image_file_path}/{langchain_paths[0]}", media_type="image/png")
571
- # else:
572
- # return {"error": "All chart generation methods failed"}
573
-
574
- # except Exception as e:
575
- # print(f"Critical chart error: {str(e)}")
576
- # return {"error": "Internal system error"}
577
-
578
-
579
-
580
-
581
-
582
-
583
- # MERGED CALL
584
-
585
- # class CSVData(BaseModel):
586
- # csv_url: str
587
- # query: str
588
- # chart_required: bool
589
-
590
- # @app.post("/api/v1/csv_chat")
591
- # async def csv_chat(csv_data: CSVData, authorization: str = Header(None)):
592
- # # Authorization verification
593
- # if not authorization or not authorization.startswith("Bearer "):
594
- # raise HTTPException(status_code=401, detail="Authorization required")
595
-
596
- # token = authorization.split(" ")[1]
597
- # if token != os.getenv("AUTH_TOKEN"):
598
- # raise HTTPException(status_code=403, detail="Invalid credentials")
599
-
600
- # csv_url = csv_data.csv_url
601
- # query = csv_data.query
602
- # chart_required = csv_data.chart_required
603
-
604
- # if(chart_required == True):
605
- # try:
606
- # # Parallel processing with thread pool
607
- # if if_initial_chart_question(query):
608
- # chart_path = await asyncio.to_thread(
609
- # langchain_csv_chart, csv_url, query, True
610
- # )
611
- # if "temp" in chart_path:
612
- # print("langchain chart Generated")
613
- # return FileResponse('temp.png', media_type="image/png")
614
- # return {"error": "Chart generation failed"}
615
-
616
- # # Groq-based chart generation
617
- # groq_result = await asyncio.to_thread(groq_chart, csv_url, query)
618
- # if groq_result == "Chart Generated":
619
- # return FileResponse("exports/charts/temp_chart.png")
620
- # # Fallback to Langchain
621
- # langchain_path = await asyncio.to_thread(
622
- # langchain_csv_chart, csv_url, query, True
623
- # )
624
- # if "temp" in langchain_path:
625
- # print("langchain chart Generated")
626
- # return FileResponse('temp.png', media_type="image/png")
627
- # return {"error": "All chart generation methods failed"}
628
-
629
- # except Exception as e:
630
- # print(f"Critical chart error: {str(e)}")
631
- # raise HTTPException(status_code=500, detail="Internal server error")
632
- # else:
633
- # try:
634
- # if if_initial_chat_question(query):
635
- # answer = await asyncio.to_thread(
636
- # langchain_csv_chat, csv_url, query, False
637
- # )
638
- # print("langchain_answer:", answer)
639
- # return {"answer": jsonable_encoder(answer)}
640
-
641
- # # Process with groq_chat first
642
- # groq_answer = await asyncio.to_thread(groq_chat, csv_url, query)
643
- # print("groq_answer:", groq_answer)
644
-
645
- # if process_answer(groq_answer) == "Empty response received.":
646
- # return {"answer": "Sorry, I couldn't find relevant data..."}
647
-
648
- # if process_answer(groq_answer):
649
- # lang_answer = await asyncio.to_thread(
650
- # langchain_csv_chat, csv_url, query, False
651
- # )
652
- # if process_answer(lang_answer):
653
- # return {"answer": "error"}
654
- # return {"answer": jsonable_encoder(lang_answer)}
655
-
656
- # return {"answer": jsonable_encoder(groq_answer)}
657
-
658
- # except Exception as e:
659
- # print(f"Error processing request: {str(e)}")
660
- # raise HTTPException(status_code=500, detail="Internal server error")
661
-
662
-
663
-
664
-
665
 
666
  # Global locks for key rotation (chart endpoints)
667
  # current_groq_chart_key_index = 0
@@ -673,86 +490,6 @@ current_langchain_chart_lock = threading.Lock()
673
  # Use a process pool to run CPU-bound charts generation
674
  process_executor = ProcessPoolExecutor(max_workers=max_cpus-2)
675
 
676
- # --- GROQ-BASED CHART GENERATION ---
677
- # def groq_chart(csv_url: str, question: str):
678
- # """
679
- # Generate a chart using the groq-based method.
680
- # Modifications:
681
- # • No deletion of a shared cache file (avoid interference).
682
- # • After chart generation, close all matplotlib figures.
683
- # • Return the full path of the saved chart.
684
- # """
685
- # global current_groq_chart_key_index, current_groq_chart_lock
686
-
687
- # for attempt in range(len(groq_api_keys)):
688
- # try:
689
- # # Instead of deleting a global cache file, you might later configure a per-request cache.
690
- # cache_db_path = "/app/cache/cache_db_0.11.db"
691
- # if os.path.exists(cache_db_path):
692
- # try:
693
- # os.remove(cache_db_path)
694
- # print(f"Deleted cache DB file: {cache_db_path}")
695
- # except Exception as e:
696
- # print(f"Error deleting cache DB file: {e}")
697
-
698
- # chart_dir = "generated_charts"
699
- # if not os.path.exists(chart_dir):
700
- # os.makedirs(chart_dir)
701
-
702
- # data = clean_data(csv_url)
703
- # with current_groq_chart_lock:
704
- # current_api_key = groq_api_keys[current_groq_chart_key_index]
705
-
706
- # llm = ChatGroq(model=model_name, api_key=current_api_key)
707
-
708
- # # Generate a unique filename and full path for the chart
709
- # chart_filename = f"chart_{uuid.uuid4().hex}.png"
710
- # chart_path = os.path.join("generated_charts", chart_filename)
711
-
712
- # # Configure your dataframe tool (e.g. using SmartDataframe) to save charts.
713
- # # (Assuming your SmartDataframe uses these settings to save charts.)
714
- # from pandasai import SmartDataframe # Import here if not already imported
715
- # df = SmartDataframe(
716
- # data,
717
- # config={
718
- # 'llm': llm,
719
- # 'save_charts': True,
720
- # 'open_charts': False,
721
- # 'save_charts_path': os.path.dirname(chart_path),
722
- # 'custom_chart_filename': chart_filename
723
- # }
724
- # )
725
-
726
- # # Append any extra instructions if needed
727
- # instructions = """
728
- # - Ensure each value is clearly visible.
729
- # - Adjust font sizes, rotate labels if necessary.
730
- # - Use a colorblind-friendly palette.
731
- # - Arrange multiple charts in a grid if needed.
732
- # """
733
- # answer = df.chat(question + instructions)
734
-
735
- # # Make sure to close figures so they don't conflict between processes
736
- # plt.close('all')
737
-
738
- # # If process_answer indicates a problem, return a failure message.
739
- # if process_answer(answer):
740
- # return "Chart not generated"
741
- # # Return the chart path that was used for saving
742
- # return chart_path
743
-
744
- # except Exception as e:
745
- # error = str(e)
746
- # if "429" in error:
747
- # with current_groq_chart_lock:
748
- # current_groq_chart_key_index = (current_groq_chart_key_index + 1) % len(groq_api_keys)
749
- # else:
750
- # print(f"Groq chart generation error: {error}")
751
- # return {"error": error}
752
-
753
- # return {"error": "All API keys exhausted for chart generation"}
754
-
755
-
756
  # --- LANGCHAIN-BASED CHART GENERATION ---
757
  def langchain_csv_chart(csv_url: str, question: str, chart_required: bool):
758
  """
 
402
  instructions = """
403
 
404
  - Please ensure that each value is clearly visible, You may need to adjust the font size, rotate the labels, or use truncation to improve readability (if needed).
405
+ - For multiple charts, arrange them in a format (2x2, 3x3, etc.)
406
  - Use colorblind-friendly palette
407
  - Read above instructions and follow them.
408
 
 
479
 
480
 
481
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
482
 
483
  # Global locks for key rotation (chart endpoints)
484
  # current_groq_chart_key_index = 0
 
490
  # Use a process pool to run CPU-bound charts generation
491
  process_executor = ProcessPoolExecutor(max_workers=max_cpus-2)
492
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
493
  # --- LANGCHAIN-BASED CHART GENERATION ---
494
  def langchain_csv_chart(csv_url: str, question: str, chart_required: bool):
495
  """
gemini_langchain_agent.py CHANGED
@@ -128,206 +128,3 @@ def langchain_gemini_csv_handler(csv_url: str, question: str, chart_required: bo
128
  print("All LLM instances have been exhausted.")
129
  return None
130
 
131
-
132
-
133
-
134
-
135
-
136
-
137
-
138
-
139
-
140
-
141
-
142
-
143
-
144
- # import os
145
- # import re
146
- # import uuid
147
- # from langchain_google_genai import ChatGoogleGenerativeAI
148
- # import pandas as pd
149
- # from langchain_core.prompts import ChatPromptTemplate
150
- # from langchain_experimental.tools import PythonAstREPLTool
151
- # from langchain_experimental.agents import create_pandas_dataframe_agent
152
- # from dotenv import load_dotenv
153
- # import numpy as np
154
- # import matplotlib.pyplot as plt
155
- # import matplotlib
156
- # import seaborn as sns
157
- # import datetime as dt
158
-
159
- # # Set the backend for matplotlib to 'Agg' to avoid GUI issues
160
- # matplotlib.use('Agg')
161
-
162
- # load_dotenv()
163
- # model_name = 'gemini-2.0-flash' # Specify the model name
164
- # google_api_keys = os.getenv("GEMINI_API_KEYS").split(",")
165
-
166
- # # Create pre-initialized LLM instances
167
- # llm_instances = [
168
- # ChatGoogleGenerativeAI(model=model_name, api_key=key)
169
- # for key in google_api_keys
170
- # ]
171
- # current_instance_index = 0 # Track current instance being used
172
-
173
- # def is_retryable_error(error: Exception) -> bool:
174
- # """Check if the error should trigger a retry with next instance"""
175
- # error_str = str(error).lower()
176
-
177
- # retry_conditions = [
178
- # # Rate limiting and quota errors
179
- # '429' in error_str,
180
- # 'quota' in error_str,
181
- # 'rate limit' in error_str,
182
- # 'resource exhausted' in error_str,
183
- # 'exceeded' in error_str,
184
- # 'limit reached' in error_str,
185
-
186
- # # Authentication and permission errors
187
- # 'permission denied' in error_str,
188
- # 'invalid api key' in error_str,
189
- # 'authentication' in error_str,
190
-
191
- # # Server errors
192
- # '500' in error_str,
193
- # '503' in error_str,
194
- # 'service unavailable' in error_str,
195
-
196
- # # Connection issues
197
- # 'timeout' in error_str,
198
- # 'connection' in error_str,
199
-
200
- # # Content policy
201
- # 'content policy' in error_str,
202
- # 'safety' in error_str,
203
- # 'blocked' in error_str
204
- # ]
205
-
206
- # return any(retry_conditions)
207
-
208
- # def create_agent(llm, data, tools):
209
- # """Create agent with tool names"""
210
- # return create_pandas_dataframe_agent(
211
- # llm,
212
- # data,
213
- # agent_type="tool-calling",
214
- # verbose=True,
215
- # allow_dangerous_code=True,
216
- # extra_tools=tools,
217
- # return_intermediate_steps=True
218
- # )
219
-
220
- # def _prompt_generator(question: str, chart_required: bool):
221
- # chat_prompt = f"""You are a senior data analyst working with CSV data. Adhere strictly to the following guidelines:
222
-
223
- # 1. **Data Verification:** Always inspect the data with `.sample(5).to_dict()` before performing any analysis.
224
- # 2. **Data Integrity:** Ensure proper handling of null values to maintain accuracy and reliability.
225
- # 3. **Communication:** Provide concise, professional, and well-structured responses.
226
- # 4. Avoid including any internal processing details or references to the methods used to generate your response (ex: based on the tool call, using the function -> These types of phrases.)
227
-
228
- # **Query:** {question}
229
- # """
230
-
231
- # chart_prompt = f"""You are a senior data analyst working with CSV data. Follow these rules STRICTLY:
232
-
233
- # 1. Generate ONE unique identifier FIRST using: unique_id = uuid.uuid4().hex
234
- # 2. Visualization requirements:
235
- # - Adjust font sizes, rotate labels (45° if needed), truncate for readability
236
- # - Figure size: (12, 6)
237
- # - Descriptive titles (fontsize=14)
238
- # - Colorblind-friendly palettes
239
- # 3. File handling rules:
240
- # - Create MAXIMUM 2 charts if absolutely necessary
241
- # - For multiple charts:
242
- # * Arrange in grid format (2x1 vertical layout preferred)
243
- # * Use SAME unique_id with suffixes:
244
- # - f"{{unique_id}}_1.png"
245
- # - f"{{unique_id}}_2.png"
246
- # - Save EXCLUSIVELY to "generated_charts" folder
247
- # - File naming: f"chart_{{unique_id}}.png" (for single chart)
248
- # 4. FINAL OUTPUT MUST BE:
249
- # - For single chart: f"generated_charts/chart_{{unique_id}}.png"
250
- # - For multiple charts: f"generated_charts/chart_{{unique_id}}.png" (combined grid image)
251
- # - **ONLY return this full path string, nothing else**
252
-
253
- # **Query:** {question}
254
-
255
- # IMPORTANT:
256
- # - Generate the unique_id FIRST before any operations
257
- # - Use THE SAME unique_id throughout entire process
258
- # - NEVER generate new UUIDs after initial creation
259
- # - Return EXACT filepath string of the final saved chart
260
- # """
261
-
262
- # if chart_required:
263
- # return ChatPromptTemplate.from_template(chart_prompt)
264
- # else:
265
- # return ChatPromptTemplate.from_template(chat_prompt)
266
-
267
- # def langchain_gemini_csv_handler(csv_url: str, question: str, chart_required: bool):
268
- # global current_instance_index
269
- # data = pd.read_csv(csv_url)
270
-
271
- # # Track first error in case all instances fail
272
- # first_error = None
273
-
274
- # while current_instance_index < len(llm_instances):
275
- # try:
276
- # llm = llm_instances[current_instance_index]
277
- # print(f"Attempting with LLM instance {current_instance_index + 1}/{len(llm_instances)}")
278
-
279
- # # Create tool with validated name
280
- # tool = PythonAstREPLTool(
281
- # locals={
282
- # "df": data,
283
- # "pd": pd,
284
- # "np": np,
285
- # "plt": plt,
286
- # "sns": sns,
287
- # "matplotlib": matplotlib,
288
- # "uuid": uuid,
289
- # "dt": dt
290
- # },
291
- # )
292
-
293
- # agent = create_agent(llm, data, [tool])
294
- # prompt = _prompt_generator(question, chart_required)
295
- # result = agent.invoke({"input": prompt})
296
- # output = result.get("output")
297
-
298
- # if output is None:
299
- # raise ValueError("Received None response from agent")
300
-
301
- # if isinstance(output, str) and any(err in output.lower() for err in ['quota', 'limit', 'exhausted']):
302
- # raise ValueError(f"API limitation detected in response: {output}")
303
-
304
- # return output
305
-
306
- # except Exception as e:
307
- # error_msg = f"Error with instance {current_instance_index}: {str(e)}"
308
- # print(error_msg)
309
-
310
- # # Store first error if not set
311
- # if first_error is None:
312
- # first_error = error_msg
313
-
314
- # # Check if we should try next instance
315
- # if is_retryable_error(e):
316
- # current_instance_index += 1
317
- # continue
318
- # else:
319
- # # Non-retryable error - return immediately
320
- # return {
321
- # "error": "Non-retryable error occurred",
322
- # "details": str(e),
323
- # "instance": current_instance_index
324
- # }
325
-
326
- # # All instances exhausted
327
- # error_response = {
328
- # "error": "All API instances failed",
329
- # "details": first_error or "Unknown error",
330
- # "attempted_instances": current_instance_index
331
- # }
332
- # print(error_response)
333
- # return error_response
 
128
  print("All LLM instances have been exhausted.")
129
  return None
130
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
groq_chart.py CHANGED
@@ -29,7 +29,7 @@ logger = logging.getLogger(__name__)
29
  instructions = """
30
 
31
  - Please ensure that each value is clearly visible, You may need to adjust the font size, rotate the labels, or use truncation to improve readability (if needed).
32
- - For multiple charts, arrange them in a grid format (2x2, 3x3, etc.)
33
  - Use colorblind-friendly palette
34
  - Read above instructions and follow them.
35
  - Please do not use any visualization library other than matplotlib or seaborn.
 
29
  instructions = """
30
 
31
  - Please ensure that each value is clearly visible, You may need to adjust the font size, rotate the labels, or use truncation to improve readability (if needed).
32
+ - For multiple charts, arrange them in a format (2x2, 3x3, etc.)
33
  - Use colorblind-friendly palette
34
  - Read above instructions and follow them.
35
  - Please do not use any visualization library other than matplotlib or seaborn.
openai_pandasai_service.py CHANGED
@@ -20,7 +20,7 @@ current_llm_index = 0
20
 
21
  instructions = """
22
  - Please ensure that each value is clearly visible, You may need to adjust the font size, rotate the labels, or use truncation to improve readability (if needed).
23
- - For multiple charts, arrange them in a grid format (2x2, 3x3, etc.)
24
  - Use professional and color-blind friendly palettes.
25
  - Do not use sns.set_palette()
26
  - Read above instructions and follow them.
 
20
 
21
  instructions = """
22
  - Please ensure that each value is clearly visible, You may need to adjust the font size, rotate the labels, or use truncation to improve readability (if needed).
23
+ - For multiple charts, arrange them in a format (2x2, 3x3, etc.)
24
  - Use professional and color-blind friendly palettes.
25
  - Do not use sns.set_palette()
26
  - Read above instructions and follow them.