Jelajahi Sumber

Switch AI backend from Claude to Gemini

- Update requirements.txt to use google-generativeai instead of anthropic
- Add Gemini API key support to config
- Refactor recommender to use Gemini Pro model
- Fix Jinja2 template syntax error in genres loop

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Brad Lance 3 bulan lalu
induk
melakukan
8c681f5d40
5 mengubah file dengan 17 tambahan dan 22 penghapusan
  1. 2 1
      .env.example
  2. 1 0
      app/config.py
  3. 12 19
      app/recommender.py
  4. 1 1
      app/templates/index.html
  5. 1 1
      requirements.txt

+ 2 - 1
.env.example

@@ -3,7 +3,8 @@ ABS_URL=https://your-audiobookshelf-server.com
 ABS_API_TOKEN=your_api_token_here
 
 # AI Configuration (use one)
-ANTHROPIC_API_KEY=your_claude_api_key_here
+GEMINI_API_KEY=your_gemini_api_key_here
+# ANTHROPIC_API_KEY=your_claude_api_key_here
 # OPENAI_API_KEY=your_openai_api_key_here
 
 # Application Configuration

+ 1 - 0
app/config.py

@@ -10,6 +10,7 @@ class Settings(BaseSettings):
     abs_api_token: str
 
     # AI Configuration
+    gemini_api_key: str | None = None
     anthropic_api_key: str | None = None
     openai_api_key: str | None = None
 

+ 12 - 19
app/recommender.py

@@ -1,17 +1,18 @@
-from anthropic import Anthropic
+import google.generativeai as genai
 from typing import List, Dict, Any
 import json
 from app.config import get_settings
 
 
 class BookRecommender:
-    """AI-powered book recommendation engine using Claude."""
+    """AI-powered book recommendation engine using Gemini."""
 
     def __init__(self):
         settings = get_settings()
-        if not settings.anthropic_api_key:
-            raise ValueError("ANTHROPIC_API_KEY not configured")
-        self.client = Anthropic(api_key=settings.anthropic_api_key)
+        if not settings.gemini_api_key:
+            raise ValueError("GEMINI_API_KEY not configured")
+        genai.configure(api_key=settings.gemini_api_key)
+        self.model = genai.GenerativeModel('gemini-pro')
 
     async def generate_recommendations(
         self,
@@ -31,7 +32,7 @@ class BookRecommender:
         # Build context from reading history
         history_text = self._format_reading_history(reading_history)
 
-        # Create prompt for Claude
+        # Create prompt for Gemini
         prompt = f"""Based on this reading history, recommend {num_recommendations} audiobooks that this person would enjoy.
 
 Reading History:
@@ -47,15 +48,11 @@ For each recommendation, provide:
 Format your response as a JSON array with objects containing: title, author, description, reason, genres.
 Only respond with the JSON array, no additional text."""
 
-        # Call Claude API
-        message = self.client.messages.create(
-            model="claude-3-5-sonnet-20241022",
-            max_tokens=2048,
-            messages=[{"role": "user", "content": prompt}]
-        )
+        # Call Gemini API
+        response = self.model.generate_content(prompt)
 
         # Parse response
-        response_text = message.content[0].text
+        response_text = response.text
         try:
             recommendations = json.loads(response_text)
             return recommendations
@@ -116,10 +113,6 @@ Only respond with the JSON array, no additional text."""
 
 Provide a thoughtful 2-3 paragraph explanation connecting specific aspects of the recommended book to their reading preferences."""
 
-        message = self.client.messages.create(
-            model="claude-3-5-sonnet-20241022",
-            max_tokens=512,
-            messages=[{"role": "user", "content": prompt}]
-        )
+        response = self.model.generate_content(prompt)
 
-        return message.content[0].text
+        return response.text

+ 1 - 1
app/templates/index.html

@@ -36,7 +36,7 @@
                             </div>
                             {% if rec.genres %}
                                 <div class="genres">
-                                    {% for genre in rec.genres.split(',') if rec.genres else [] %}
+                                    {% for genre in rec.genres.split(',') %}
                                     <span class="genre-tag">{{ genre.strip() }}</span>
                                     {% endfor %}
                                 </div>

+ 1 - 1
requirements.txt

@@ -5,6 +5,6 @@ python-dotenv==1.0.0
 httpx==0.26.0
 sqlalchemy==2.0.25
 aiosqlite==0.19.0
-anthropic==0.18.1
+google-generativeai==0.3.2
 pydantic==2.5.3
 pydantic-settings==2.1.0