multi1/api_handlers.py

124 lines
5.4 KiB
Python

import json
import requests
import groq
import time
class OllamaHandler:
def __init__(self, url, model):
self.url = url
self.model = model
def make_api_call(self, messages, max_tokens, is_final_answer=False):
for attempt in range(3):
try:
response = requests.post(
f"{self.url}/api/chat",
json={
"model": self.model,
"messages": messages,
"stream": False,
"format": "json",
"options": {
"num_predict": max_tokens,
"temperature": 0.2
}
}
)
response.raise_for_status()
return json.loads(response.json()["message"]["content"])
except Exception as e:
if attempt == 2:
return self._error_response(str(e), is_final_answer)
time.sleep(1)
def _error_response(self, error_msg, is_final_answer):
if is_final_answer:
return {"title": "Error", "content": f"Failed to generate final answer after 3 attempts. Error: {error_msg}"}
else:
return {"title": "Error", "content": f"Failed to generate step after 3 attempts. Error: {error_msg}", "next_action": "final_answer"}
class PerplexityHandler:
def __init__(self, api_key, model):
self.api_key = api_key
self.model = model
def make_api_call(self, messages, max_tokens, is_final_answer=False):
# Quick dirty fix for API calls in perplexity that removes the assistant message
#messages[0]["content"] = messages[0]["content"] + " You will always respond ONLY with JSON with the following format: {'title': 'Title of the step', 'content': 'Content of the step', 'next_action': 'continue' or 'final_answer'}. You are not allowed to respond with anything else or any additional text. "
if not is_final_answer:
for i in range(len(messages)):
if messages[i]["role"] == "assistant":
messages.pop(i)
for attempt in range(3):
try:
url = "https://api.perplexity.ai/chat/completions"
payload = {"model": self.model, "messages": messages}
headers = {
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json",
}
response = requests.post(url, json=payload, headers=headers)
# Add specific handling for 400 error
if response.status_code == 400:
error_content = response.json()
print(f"HTTP 400 Error: {error_content}")
return self._error_response(f"HTTP 400 Error: {error_content}", is_final_answer)
response.raise_for_status()
content = response.json()["choices"][0]["message"]["content"]
print("Content: ", content)
return json.loads(content)
except json.JSONDecodeError:
print("Warning: content is not a valid JSON, returning raw response")
# Better detection of final answer in the raw response for Perplexity
forced_final_answer = False
if '"next_action": "final_answer"' in content.lower().strip():
forced_final_answer = True
print("Forced final answer: ", forced_final_answer)
return {
"title": "Raw Response",
"content": content,
"next_action": "final_answer" if (is_final_answer|forced_final_answer) else "continue"
}
except requests.exceptions.RequestException as e:
print(f"Request failed: {e}")
if attempt == 2:
return self._error_response(str(e), is_final_answer)
time.sleep(1)
def _error_response(self, error_msg, is_final_answer):
return {
"title": "Error",
"content": f"API request failed after 3 attempts. Error: {error_msg}",
"next_action": "final_answer",
}
class GroqHandler:
def __init__(self):
self.client = groq.Groq()
def make_api_call(self, messages, max_tokens, is_final_answer=False):
for attempt in range(3):
try:
response = self.client.chat.completions.create(
model="llama-3.1-70b-versatile",
messages=messages,
max_tokens=max_tokens,
temperature=0.2,
response_format={"type": "json_object"}
)
return json.loads(response.choices[0].message.content)
except Exception as e:
if attempt == 2:
return self._error_response(str(e), is_final_answer)
time.sleep(1)
def _error_response(self, error_msg, is_final_answer):
if is_final_answer:
return {"title": "Error", "content": f"Failed to generate final answer after 3 attempts. Error: {error_msg}"}
else:
return {"title": "Error", "content": f"Failed to generate step after 3 attempts. Error: {error_msg}", "next_action": "final_answer"}