File size: 7,796 Bytes
0a40ab8 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# src/utils/groq_client.py
import os
from groq import Groq, RateLimitError, APIError
import time
# Initialize Groq client using environment variable
# Ensure GROQ_API_KEY is set in the environment where the Flask app runs
client = Groq(
api_key=os.environ.get("GROQ_API_KEY"),
)
# Define a default model
DEFAULT_MODEL = "llama3-8b-8192" # Or choose another suitable model like llama3-70b-8192, mixtral-8x7b-32768
def call_groq(prompt: str, system_prompt: str = "You are a helpful assistant specializing in legislative analysis and drafting.", model: str = DEFAULT_MODEL, max_retries: int = 3, initial_delay: int = 1) -> str | None:
"""Calls the Groq API with a given prompt and handles basic errors/retries."""
if not client.api_key:
print("Error: GROQ_API_KEY environment variable not set.")
return "Error: Groq API key not configured."
retries = 0
delay = initial_delay
while retries < max_retries:
try:
chat_completion = client.chat.completions.create(
messages=[
{
"role": "system",
"content": system_prompt,
},
{
"role": "user",
"content": prompt,
}
],
model=model,
# Optional parameters:
# temperature=0.7,
# max_tokens=1024,
# top_p=1,
# stop=None,
# stream=False,
)
return chat_completion.choices[0].message.content
except RateLimitError as e:
retries += 1
print(f"Rate limit exceeded. Retrying in {delay} seconds... (Attempt {retries}/{max_retries})")
time.sleep(delay)
delay *= 2 # Exponential backoff
except APIError as e:
print(f"Groq API Error: {e.status_code} - {e.message}")
# Depending on the error, you might want to retry or just return None/error message
return f"Error: Groq API request failed ({e.status_code})."
except Exception as e:
print(f"An unexpected error occurred calling Groq: {e}")
return f"Error: An unexpected error occurred while contacting the AI model."
print(f"Failed to call Groq API after {max_retries} retries.")
return "Error: AI model request failed after multiple retries due to rate limits."
# --- Specific Task Functions ---
def generate_draft_content(policy_intent: str) -> str | None:
"""Uses Groq to generate initial draft content based on policy intent."""
system_prompt = "You are an AI assistant specialized in legislative drafting. Based on the provided policy intent, generate a concise initial draft for a new regulation or law. Focus on clear, actionable language suitable for legislation."
prompt = f"Policy Intent: {policy_intent}\n\nGenerate an initial legislative draft based on this intent:"
return call_groq(prompt, system_prompt)
def perform_impact_analysis(document_content: str, analysis_type: str) -> tuple[str | None, float | None, str | None]:
"""Uses Groq to perform impact analysis on a given document.
Returns: (predicted_impact, confidence_score, rationale)
"""
system_prompt = f"You are an AI legislative analyst. Analyze the provided legislative text and predict its potential {analysis_type.lower()} impact. Provide a summary of the predicted impact, a confidence score (0.0 to 1.0), and a brief rationale for your prediction."
prompt = f"Legislative Text:\n```\n{document_content}\n```\n\nAnalyze the {analysis_type.lower()} impact of this text. Format your response strictly as follows:\nPredicted Impact: [Your summary here]\nConfidence Score: [A number between 0.0 and 1.0]\nRationale: [Your explanation here]"
response = call_groq(prompt, system_prompt)
if response and response.startswith("Predicted Impact:"):
try:
lines = response.split("\n")
impact = lines[0].replace("Predicted Impact:", "").strip()
score_line = next((line for line in lines if line.startswith("Confidence Score:")), None)
rationale_line = next((line for line in lines if line.startswith("Rationale:")), None)
score = None
if score_line:
try:
score_str = score_line.replace("Confidence Score:", "").strip()
score = float(score_str)
if not (0.0 <= score <= 1.0):
score = None # Invalid score
except ValueError:
score = None # Could not parse score
rationale = None
if rationale_line:
# Find the start index of Rationale and take everything after it
rationale_start_index = response.find("Rationale:")
if rationale_start_index != -1:
rationale = response[rationale_start_index + len("Rationale:"):].strip()
else: # Fallback if split didn't work as expected
rationale = rationale_line.replace("Rationale:", "").strip()
return impact, score, rationale
except Exception as e:
print(f"Error parsing Groq impact analysis response: {e}")
return f"Error parsing AI response: {response}", None, None
else:
# Return the raw response or error message if parsing failed
return response or "Error: No response from AI model.", None, None
def generate_recommendation(criteria: str) -> tuple[str | None, str | None, str | None, str | None]:
"""Uses Groq to generate a legislative recommendation based on criteria.
Returns: (recommendation_type, details, rationale, priority)
"""
system_prompt = "You are an AI legislative analyst. Based on the provided criteria, suggest a legislative recommendation (e.g., Update, Consolidation, Removal). Provide details, rationale, and a priority level (Low, Medium, High)."
prompt = f"Criteria for Recommendation: {criteria}\n\nGenerate a legislative recommendation based on these criteria. Format your response strictly as follows:\nType: [Update/Consolidation/Removal]\nDetails: [Specific recommendation details]\nRationale: [Justification for the recommendation]\nPriority: [Low/Medium/High]"
response = call_groq(prompt, system_prompt)
if response and response.startswith("Type:"):
try:
lines = response.split("\n")
rec_type = lines[0].replace("Type:", "").strip()
details_line = next((line for line in lines if line.startswith("Details:")), None)
rationale_line = next((line for line in lines if line.startswith("Rationale:")), None)
priority_line = next((line for line in lines if line.startswith("Priority:")), None)
details = details_line.replace("Details:", "").strip() if details_line else None
rationale = rationale_line.replace("Rationale:", "").strip() if rationale_line else None
priority = priority_line.replace("Priority:", "").strip() if priority_line else None
# Basic validation for priority
if priority not in ["Low", "Medium", "High"]:
priority = "Medium" # Default if invalid
return rec_type, details, rationale, priority
except Exception as e:
print(f"Error parsing Groq recommendation response: {e}")
return "Error", f"Error parsing AI response: {response}", None, "Medium"
else:
return "Error", response or "Error: No response from AI model.", None, "Medium"
|