Implement complete Eugen Twitch chatbot
This commit implements the full Eugen bot based on specifications in CLAUDE.md and eugen_claude.md. Features implemented: - Smart name recognition (@Eugen, Eugen:, etc.) - Persistent conversation memory per user (max 25 messages, 1 hour retention) - Perplexity Sonar API integration for AI responses - Live monitoring dashboard with PySimpleGUI - Setup wizard for first-time configuration - Comprehensive logging (main log + API debug log) Files added: - config.py: Configuration management from .env and config.json - utils.py: MentionDetector and Logger utility classes - memory.py: ConversationMemory for persistent chat history - ai_provider.py: PerplexityProvider for API integration - gui.py: Dashboard and SetupWizard GUI components - chatbot.py: Main EugenBot orchestrator with IRC handling - requirements.txt: Python dependencies - .env.example: Template for environment variables - .gitignore: Renamed from gitignore for proper Git usage Updated: - README.md: Complete usage instructions and documentation The bot is ready to use - users just need to add their API keys and run python chatbot.py
This commit is contained in:
parent
742c907a5a
commit
963a65536f
10 changed files with 1350 additions and 2 deletions
161
ai_provider.py
Normal file
161
ai_provider.py
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
"""
|
||||
Perplexity API Provider for Eugen Bot
|
||||
Handles communication with Perplexity Sonar API
|
||||
"""
|
||||
import httpx
|
||||
import json
|
||||
import time
|
||||
from typing import List, Dict, Optional
|
||||
|
||||
|
||||
class PerplexityProvider:
|
||||
"""Communicates with Perplexity API for AI responses"""
|
||||
|
||||
def __init__(self, api_key, model="sonar-pro", max_tokens=450, temperature=0.7):
|
||||
"""
|
||||
Initialize Perplexity API provider
|
||||
|
||||
Args:
|
||||
api_key (str): Perplexity API key
|
||||
model (str): Model to use (default: sonar-pro)
|
||||
max_tokens (int): Maximum tokens in response
|
||||
temperature (float): Sampling temperature
|
||||
"""
|
||||
self.api_key = api_key
|
||||
self.model = model
|
||||
self.max_tokens = max_tokens
|
||||
self.temperature = temperature
|
||||
self.base_url = "https://api.perplexity.ai"
|
||||
|
||||
# Statistics
|
||||
self.total_requests = 0
|
||||
self.total_tokens = 0
|
||||
self.total_errors = 0
|
||||
self.last_response_time = 0
|
||||
|
||||
async def get_response(self, messages):
|
||||
"""
|
||||
Send messages to Perplexity API and get response
|
||||
|
||||
Args:
|
||||
messages (list): List of message dicts with 'role' and 'content'
|
||||
Example: [
|
||||
{"role": "system", "content": "You are..."},
|
||||
{"role": "user", "content": "Hello"}
|
||||
]
|
||||
|
||||
Returns:
|
||||
str: AI response content
|
||||
None: If error occurred
|
||||
"""
|
||||
headers = {
|
||||
"Authorization": f"Bearer {self.api_key}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
payload = {
|
||||
"model": self.model,
|
||||
"messages": messages,
|
||||
"max_tokens": self.max_tokens,
|
||||
"temperature": self.temperature
|
||||
}
|
||||
|
||||
start_time = time.time()
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.post(
|
||||
f"{self.base_url}/chat/completions",
|
||||
json=payload,
|
||||
headers=headers
|
||||
)
|
||||
|
||||
self.last_response_time = time.time() - start_time
|
||||
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
content = data['choices'][0]['message']['content']
|
||||
tokens_used = data.get('usage', {}).get('total_tokens', 0)
|
||||
|
||||
# Update statistics
|
||||
self.total_requests += 1
|
||||
self.total_tokens += tokens_used
|
||||
|
||||
return content
|
||||
else:
|
||||
self.total_errors += 1
|
||||
error_msg = f"API Error {response.status_code}: {response.text}"
|
||||
print(error_msg)
|
||||
return None
|
||||
|
||||
except httpx.TimeoutException:
|
||||
self.total_errors += 1
|
||||
print("API Timeout: Request took too long")
|
||||
return None
|
||||
except Exception as e:
|
||||
self.total_errors += 1
|
||||
print(f"API Error: {str(e)}")
|
||||
return None
|
||||
|
||||
async def validate_api_key(self):
|
||||
"""
|
||||
Validate API key with a simple test request
|
||||
|
||||
Returns:
|
||||
bool: True if API key is valid
|
||||
"""
|
||||
test_messages = [
|
||||
{"role": "user", "content": "test"}
|
||||
]
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=5.0) as client:
|
||||
response = await client.post(
|
||||
f"{self.base_url}/chat/completions",
|
||||
json={
|
||||
"model": self.model,
|
||||
"messages": test_messages,
|
||||
"max_tokens": 10
|
||||
},
|
||||
headers={
|
||||
"Authorization": f"Bearer {self.api_key}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
)
|
||||
return response.status_code == 200
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
def get_statistics(self):
|
||||
"""
|
||||
Get API usage statistics
|
||||
|
||||
Returns:
|
||||
dict: Statistics including requests, tokens, errors, avg response time
|
||||
"""
|
||||
avg_response_time = self.last_response_time if self.total_requests > 0 else 0
|
||||
success_rate = (
|
||||
((self.total_requests - self.total_errors) / self.total_requests * 100)
|
||||
if self.total_requests > 0
|
||||
else 0
|
||||
)
|
||||
|
||||
# Rough cost calculation (example pricing, adjust as needed)
|
||||
# Perplexity pricing varies, this is an estimate
|
||||
estimated_cost = self.total_tokens * 0.0003 / 1000 # $0.0003 per 1K tokens
|
||||
|
||||
return {
|
||||
"total_requests": self.total_requests,
|
||||
"total_tokens": self.total_tokens,
|
||||
"total_errors": self.total_errors,
|
||||
"avg_response_time": avg_response_time,
|
||||
"success_rate": success_rate,
|
||||
"estimated_cost": estimated_cost
|
||||
}
|
||||
|
||||
def reset_statistics(self):
|
||||
"""Reset all statistics counters"""
|
||||
self.total_requests = 0
|
||||
self.total_tokens = 0
|
||||
self.total_errors = 0
|
||||
self.last_response_time = 0
|
||||
Loading…
Add table
Add a link
Reference in a new issue