chore: switch to DeepSeek API + sentence-transformers for free deployment

- Replace OpenAI LLM with DeepSeek (deepseek-chat) via OpenAI-compatible client
- Replace OpenAI embeddings with local sentence-transformers (all-MiniLM-L6-v2)
- Pre-download embedding model during Docker build
- Add .gitignore

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Power BI Dev
2026-06-04 09:04:21 +07:00
parent f62a711f5d
commit fddd3644ae
7 changed files with 27 additions and 15 deletions
+4 -3
View File
@@ -4,10 +4,11 @@ from dotenv import load_dotenv
load_dotenv()
TELEGRAM_BOT_TOKEN = os.environ["TELEGRAM_BOT_TOKEN"]
OPENAI_API_KEY = os.environ["OPENAI_API_KEY"]
OPENAI_MODEL = os.getenv("OPENAI_MODEL", "gpt-4o")
OPENAI_EMBEDDING_MODEL = os.getenv("OPENAI_EMBEDDING_MODEL", "text-embedding-3-small")
DEEPSEEK_API_KEY = os.environ["DEEPSEEK_API_KEY"]
DEEPSEEK_MODEL = os.getenv("DEEPSEEK_MODEL", "deepseek-chat")
DEEPSEEK_BASE_URL = "https://api.deepseek.com"
ADMIN_TELEGRAM_ID = int(os.environ["ADMIN_TELEGRAM_ID"])
DB_PATH = os.getenv("DB_PATH", "/app/data/second_brain.db")
CHROMA_PATH = os.getenv("CHROMA_PATH", "/app/data/chromadb")
UPLOAD_PATH = os.getenv("UPLOAD_PATH", "/app/data/uploads")
EMBEDDING_MODEL = os.getenv("EMBEDDING_MODEL", "all-MiniLM-L6-v2")
+4 -4
View File
@@ -2,13 +2,13 @@ from pathlib import Path
from telegram import Update
from telegram.ext import ContextTypes
from openai import AsyncOpenAI
from config import OPENAI_API_KEY, OPENAI_MODEL, ADMIN_TELEGRAM_ID
from config import DEEPSEEK_API_KEY, DEEPSEEK_BASE_URL, DEEPSEEK_MODEL, ADMIN_TELEGRAM_ID
import database as db
import rag
import document as doc_processor
from guard import is_academic_topic, REJECT_MESSAGE
_client = AsyncOpenAI(api_key=OPENAI_API_KEY)
_client = AsyncOpenAI(api_key=DEEPSEEK_API_KEY, base_url=DEEPSEEK_BASE_URL)
ACADEMIC_SYSTEM_PROMPT = (
"Anda adalah asisten akademik personal untuk dosen di perguruan tinggi Indonesia. "
@@ -128,7 +128,7 @@ async def ask(update: Update, context: ContextTypes.DEFAULT_TYPE):
await update.message.chat.send_action("typing")
# Guard: hanya izinkan topik akademik
if not await is_academic_topic(question, _client, OPENAI_MODEL):
if not await is_academic_topic(question, _client, DEEPSEEK_MODEL):
await update.message.reply_text(REJECT_MESSAGE)
return
@@ -154,7 +154,7 @@ async def ask(update: Update, context: ContextTypes.DEFAULT_TYPE):
try:
response = await _client.chat.completions.create(
model=OPENAI_MODEL,
model=DEEPSEEK_MODEL,
messages=messages,
max_tokens=1500,
)
+5 -5
View File
@@ -1,10 +1,10 @@
import asyncio
import chromadb
from openai import AsyncOpenAI
from config import CHROMA_PATH, OPENAI_API_KEY, OPENAI_EMBEDDING_MODEL
from sentence_transformers import SentenceTransformer
from config import CHROMA_PATH, EMBEDDING_MODEL
_client = AsyncOpenAI(api_key=OPENAI_API_KEY)
_chroma = chromadb.PersistentClient(path=CHROMA_PATH)
_embedding_model = SentenceTransformer(EMBEDDING_MODEL)
def _get_collection(name: str):
@@ -12,8 +12,8 @@ def _get_collection(name: str):
async def _embed(text: str) -> list:
resp = await _client.embeddings.create(model=OPENAI_EMBEDDING_MODEL, input=text)
return resp.data[0].embedding
embedding = await asyncio.to_thread(_embedding_model.encode, text)
return embedding.tolist()
async def add_memory(user_id: int, memory_id: int, content: str, scope: str = "private"):