Yaswanth123 commited on
Commit
9064aae
·
verified ·
1 Parent(s): fd80499

Update config.py

Browse files
Files changed (1) hide show
  1. config.py +106 -23
config.py CHANGED
@@ -1,9 +1,11 @@
1
  # FILE: config.py
2
- # (Corrected and complete version with all constants)
3
 
4
  import os
5
  import dspy
6
  import logging
 
 
7
  from dotenv import load_dotenv
8
  from dspy_llm_wrapper import SyncCustomGeminiDspyLM
9
 
@@ -14,43 +16,125 @@ load_dotenv()
14
  logging.basicConfig(level=logging.INFO, format='{levelname} {asctime} {name}: {message}', style='{')
15
  logger = logging.getLogger(__name__)
16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  API_KEY = os.getenv("GOOGLE_API_KEY")
18
 
19
- def initialize_dspy():
20
- """Configures and returns the DSPy Language Model instance."""
21
- if not API_KEY:
22
- logger.error("FATAL: GOOGLE_API_KEY not found. Cannot initialize DSPy.")
 
 
 
 
 
 
 
 
 
 
23
  return None
24
-
 
 
25
  try:
26
- LITELLM_MODEL_STRING = "gemini/gemini-2.5-flash-preview-04-17"
27
  custom_lm = SyncCustomGeminiDspyLM(
28
- model=LITELLM_MODEL_STRING,
29
- api_key=API_KEY,
30
- temperature=0.7,
31
  )
32
- dspy.settings.configure(lm=custom_lm)
33
- logger.info(f"DSPy configured globally with model: {LITELLM_MODEL_STRING}")
34
- return custom_lm
35
  except Exception as e:
36
- logger.error(f"Fatal error configuring DSPy: {e}")
37
  return None
38
 
39
- # --- Application Constants ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
 
41
- # State Keys for managing the conversation state
 
 
 
 
 
 
 
 
42
  STATE_STAGE = "stage"
43
  STATE_HISTORY = "conversation_history"
44
  STATE_FINAL_SYLLABUS = "final_syllabus_xml"
45
  STATE_EXPLAINER_PROMPT = "explainer_system_prompt"
46
  STATE_EXPLANATION_START_INDEX = "explanation_start_index"
47
- STATE_CURRENT_TITLE = "current_title" # <-- ADDED
48
- STATE_GENERATED_TITLE = "generated_title" # <-- ADDED
49
  STATE_RESOURCE_SUMMARY_OVERVIEW = "resource_summary_overview_for_manager"
50
  STATE_RESOURCE_TYPE_FOR_SYLLABUS = "resource_type_for_syllabus_gen"
51
  STATE_RESOURCE_CONTENT_JSON_FOR_SYLLABUS = "resource_content_json_for_syllabus_gen"
 
 
52
 
53
- # Flag Keys for UI updates
54
  STATE_DISPLAY_SYLLABUS_FLAG = "display_syllabus_flag"
55
  STATE_TRANSITION_EXPLAINER_FLAG = "transition_to_explainer_flag"
56
 
@@ -59,9 +143,8 @@ STAGE_START = "START"
59
  STAGE_NEGOTIATING = "NEGOTIATING"
60
  STAGE_EXPLAINING = "EXPLAINING"
61
  STAGE_ERROR = "ERROR"
62
- STATE_UPLOADED_FILENAMES = "uploaded_filenames_list"
63
 
64
  # Chat Logic Constants
65
- DEFAULT_CHAT_TITLE = "New Chat" # <-- ADDED
66
- TITLE_GENERATION_THRESHOLD = 4 # <-- ADDED
67
- TITLE_MAX_HISTORY_SNIPPET_FOR_TITLE = 6 # <-- ADDED
 
1
  # FILE: config.py
2
+ # (Corrected and complete version with all constants and RateLimiter class)
3
 
4
  import os
5
  import dspy
6
  import logging
7
+ import time
8
+ from datetime import datetime, timedelta
9
  from dotenv import load_dotenv
10
  from dspy_llm_wrapper import SyncCustomGeminiDspyLM
11
 
 
16
  logging.basicConfig(level=logging.INFO, format='{levelname} {asctime} {name}: {message}', style='{')
17
  logger = logging.getLogger(__name__)
18
 
19
+ # --- Rate Limiter Class ---
20
+ # Integrated as per your request. App.py will instantiate this.
21
+ class RateLimiter:
22
+ """Manages call frequency to an API to stay within defined limits."""
23
+ def __init__(self, max_calls: int = 7, time_period: int = 60):
24
+ """
25
+ Initializes the RateLimiter.
26
+ Args:
27
+ max_calls (int): The maximum number of calls allowed in the time period.
28
+ time_period (int): The time period in seconds.
29
+ """
30
+ if not isinstance(max_calls, int) or max_calls <= 0:
31
+ raise ValueError("max_calls must be a positive integer.")
32
+ if not isinstance(time_period, int) or time_period <= 0:
33
+ raise ValueError("time_period must be a positive integer.")
34
+
35
+ self.max_calls = max_calls
36
+ self.time_period = time_period
37
+ self.call_timestamps = []
38
+ self.total_calls_made = 0
39
+ logger.info(f"Rate Limiter Initialized: Max {self.max_calls} calls per {self.time_period} seconds.")
40
+
41
+ def wait_if_needed(self):
42
+ """
43
+ Blocks execution if the call rate would be exceeded. Waits until the next call is allowed.
44
+ """
45
+ # Prune timestamps older than the time period
46
+ current_time = datetime.now()
47
+ self.call_timestamps = [ts for ts in self.call_timestamps if current_time - ts < timedelta(seconds=self.time_period)]
48
+
49
+ # If the limit is reached, calculate wait time
50
+ if len(self.call_timestamps) >= self.max_calls:
51
+ oldest_call_in_window = self.call_timestamps[0]
52
+ time_to_wait = (oldest_call_in_window + timedelta(seconds=self.time_period)) - current_time
53
+ wait_seconds = time_to_wait.total_seconds()
54
+
55
+ if wait_seconds > 0:
56
+ logger.warning(f"[Rate Limiter]: Limit of {self.max_calls} calls reached. Waiting for {wait_seconds:.2f} seconds.")
57
+ time.sleep(wait_seconds) # Block execution
58
+
59
+ # Record the new call timestamp and proceed
60
+ self.call_timestamps.append(datetime.now())
61
+ self.total_calls_made += 1
62
+ logger.info(f"[Rate Limiter]: Call #{self.total_calls_made} permitted.")
63
+
64
+ # --- DSPy Initialization ---
65
  API_KEY = os.getenv("GOOGLE_API_KEY")
66
 
67
+ def initialize_dspy(
68
+ model_name: str = "gemini/gemini-2.5-flash-preview-04-17",
69
+ api_key: str = None,
70
+ **kwargs
71
+ ) -> "SyncCustomGeminiDspyLM | None":
72
+
73
+ logging.info(f"Attempting to initialize DSPy with model: {model_name}")
74
+
75
+ # 1. Resolve API Key from argument or environment variable
76
+ resolved_api_key = api_key or os.getenv("GOOGLE_API_KEY")
77
+ if not resolved_api_key:
78
+ logging.error(
79
+ "FATAL: GOOGLE_API_KEY not provided as an argument or found in environment variables."
80
+ )
81
  return None
82
+
83
+ # 2. Instantiate the Language Model with default kwargs
84
+ lm_kwargs = {"temperature": 0.7, **kwargs}
85
  try:
 
86
  custom_lm = SyncCustomGeminiDspyLM(
87
+ model=model_name,
88
+ api_key=resolved_api_key,
89
+ **lm_kwargs
90
  )
 
 
 
91
  except Exception as e:
92
+ logging.error(f"Failed to instantiate SyncCustomGeminiDspyLM: {e}", exc_info=True)
93
  return None
94
 
95
+ # 3. Perform a live verification call to ensure credentials are valid
96
+ try:
97
+ logging.info("Verifying credentials with a test API call...")
98
+ # Use the LM's __call__ directly for a simple, raw test
99
+ test_response = custom_lm(prompt="Hello, this is a test. Respond with 'OK'.")
100
+
101
+ # The __call__ method returns a list. Check for an empty list or an error message.
102
+ if not test_response or "[ERROR:" in test_response[0]:
103
+ raise ValueError(f"Test call failed. Response: {test_response}")
104
+
105
+
106
+ logging.info("LM verification successful.")
107
+ except Exception as e:
108
+ logging.error(
109
+ f"FATAL: LM verification failed for model '{model_name}'. "
110
+ f"Please check your API key, model name, and network connection. Error: {e}",
111
+ exc_info=True
112
+ )
113
+ return None
114
 
115
+ # 4. Configure DSPy glo bally if verification passes
116
+ dspy.settings.configure(lm=custom_lm)
117
+ logging.info(
118
+ f"DSPy successfully configured globally with validated model: {model_name}"
119
+ )
120
+
121
+ return test_response# --- Application Constants ---
122
+
123
+ # State Keys
124
  STATE_STAGE = "stage"
125
  STATE_HISTORY = "conversation_history"
126
  STATE_FINAL_SYLLABUS = "final_syllabus_xml"
127
  STATE_EXPLAINER_PROMPT = "explainer_system_prompt"
128
  STATE_EXPLANATION_START_INDEX = "explanation_start_index"
129
+ STATE_CURRENT_TITLE = "current_title"
130
+ STATE_GENERATED_TITLE = "generated_title"
131
  STATE_RESOURCE_SUMMARY_OVERVIEW = "resource_summary_overview_for_manager"
132
  STATE_RESOURCE_TYPE_FOR_SYLLABUS = "resource_type_for_syllabus_gen"
133
  STATE_RESOURCE_CONTENT_JSON_FOR_SYLLABUS = "resource_content_json_for_syllabus_gen"
134
+ STATE_UPLOADED_FILENAMES = "uploaded_filenames_list"
135
+ STATE_IS_FIRST_TURN = "is_first_turn" # New state key for file upload logic
136
 
137
+ # Flag Keys
138
  STATE_DISPLAY_SYLLABUS_FLAG = "display_syllabus_flag"
139
  STATE_TRANSITION_EXPLAINER_FLAG = "transition_to_explainer_flag"
140
 
 
143
  STAGE_NEGOTIATING = "NEGOTIATING"
144
  STAGE_EXPLAINING = "EXPLAINING"
145
  STAGE_ERROR = "ERROR"
 
146
 
147
  # Chat Logic Constants
148
+ DEFAULT_CHAT_TITLE = "New Chat"
149
+ TITLE_GENERATION_THRESHOLD = 4
150
+ TITLE_MAX_HISTORY_SNIPPET_FOR_TITLE = 6