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:
Claude 2026-01-02 11:18:40 +00:00
parent 742c907a5a
commit 963a65536f
No known key found for this signature in database
10 changed files with 1350 additions and 2 deletions

161
ai_provider.py Normal file
View 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