indahPurnamaSarii commited on
Commit ·
f01f577
1
Parent(s): cc202af
Debugging: Menjalankan versi ringan tanpa Chroma/Embeddings
Browse files- Dockerfile +0 -16
- app.py +9 -102
Dockerfile
CHANGED
|
@@ -1,21 +1,5 @@
|
|
| 1 |
-
# Memulai dari gambar dasar Python versi 3.9
|
| 2 |
FROM python:3.9-slim
|
| 3 |
-
|
| 4 |
-
# Menetapkan direktori kerja di dalam container
|
| 5 |
WORKDIR /code
|
| 6 |
-
|
| 7 |
-
# 1. Salin SEMUA file proyek terlebih dahulu
|
| 8 |
COPY . .
|
| 9 |
-
|
| 10 |
-
# 2. Instal semua library yang dibutuhkan dari requirements.txt
|
| 11 |
RUN pip install --no-cache-dir --upgrade -r requirements.txt
|
| 12 |
-
|
| 13 |
-
# 3. Jalankan skrip pra-unduh model
|
| 14 |
-
RUN python download_model.py
|
| 15 |
-
|
| 16 |
-
# 4. Membuat dan menetapkan folder cache
|
| 17 |
-
RUN mkdir -p /app/.cache
|
| 18 |
-
ENV SENTENCE_TRANSFORMERS_HOME=/app/.cache
|
| 19 |
-
|
| 20 |
-
# 5. Perintah untuk menjalankan aplikasi saat container dimulai
|
| 21 |
CMD ["gunicorn", "--bind", "0.0.0.0:7860", "--workers", "1", "app:app"]
|
|
|
|
|
|
|
| 1 |
FROM python:3.9-slim
|
|
|
|
|
|
|
| 2 |
WORKDIR /code
|
|
|
|
|
|
|
| 3 |
COPY . .
|
|
|
|
|
|
|
| 4 |
RUN pip install --no-cache-dir --upgrade -r requirements.txt
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
CMD ["gunicorn", "--bind", "0.0.0.0:7860", "--workers", "1", "app:app"]
|
app.py
CHANGED
|
@@ -1,132 +1,39 @@
|
|
| 1 |
-
from flask import Flask, render_template, request, jsonify
|
| 2 |
from langchain_google_genai import ChatGoogleGenerativeAI
|
| 3 |
-
from langchain_huggingface import HuggingFaceEmbeddings
|
| 4 |
-
from langchain_chroma import Chroma
|
| 5 |
-
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
|
| 6 |
-
from langchain.chains import create_history_aware_retriever, create_retrieval_chain
|
| 7 |
-
from langchain.chains.combine_documents import create_stuff_documents_chain
|
| 8 |
-
from langchain_core.messages import HumanMessage, AIMessage
|
| 9 |
from dotenv import load_dotenv
|
| 10 |
import os
|
| 11 |
|
| 12 |
-
# Memuat variabel lingkungan dari file .env
|
| 13 |
load_dotenv()
|
| 14 |
|
| 15 |
app = Flask(__name__, template_folder='templates')
|
| 16 |
-
app.secret_key = os.urandom(24)
|
| 17 |
-
|
| 18 |
-
# --- Inisialisasi Komponen Utama (dilakukan sekali saat server dimulai) ---
|
| 19 |
-
vectorstore = None
|
| 20 |
llm = None
|
| 21 |
-
retriever = None
|
| 22 |
|
| 23 |
try:
|
| 24 |
-
# 1. Memuat Vectorstore (Database Chroma) yang sudah dibuat oleh vector_embeddings.py
|
| 25 |
-
vectorstore = Chroma(
|
| 26 |
-
persist_directory="data",
|
| 27 |
-
embedding_function=HuggingFaceEmbeddings(model_name="sentence-transformers/bert-base-nli-max-tokens")
|
| 28 |
-
)
|
| 29 |
-
# Membuat retriever untuk mengambil informasi dari vectorstore
|
| 30 |
-
retriever = vectorstore.as_retriever(search_kwargs={"k": 5})
|
| 31 |
-
print("Vectorstore berhasil dimuat dan retriever dibuat.")
|
| 32 |
-
except Exception as e:
|
| 33 |
-
print(f"GALAT PENTING: Kesalahan saat memuat vectorstore Chroma: {e}")
|
| 34 |
-
print("Pastikan Anda sudah menjalankan 'vector_embeddings.py' terlebih dahulu.")
|
| 35 |
-
|
| 36 |
-
try:
|
| 37 |
-
# 2. Menyiapkan Model AI (LLM)
|
| 38 |
llm = ChatGoogleGenerativeAI(model="gemini-1.5-flash", temperature=0.2)
|
| 39 |
print("Model AI (Gemini) berhasil diinisialisasi.")
|
| 40 |
except Exception as e:
|
| 41 |
print(f"GALAT PENTING: Gagal menginisialisasi model Gemini: {e}")
|
| 42 |
-
print("Pastikan GOOGLE_API_KEY Anda sudah benar di file .env.")
|
| 43 |
-
|
| 44 |
-
# --- Rute Aplikasi Flask ---
|
| 45 |
|
| 46 |
@app.route('/')
|
| 47 |
def home():
|
| 48 |
-
# --- KODE DEBUGGING BARU (Bisa dihapus nanti) ---
|
| 49 |
-
template_folder_path = os.path.join(os.path.dirname(__file__), 'templates')
|
| 50 |
-
print("--- DEBUGGING INFO ---")
|
| 51 |
-
print(f"Mencari folder templates di path: {template_folder_path}")
|
| 52 |
-
if os.path.exists(template_folder_path):
|
| 53 |
-
files_in_templates = os.listdir(template_folder_path)
|
| 54 |
-
print(f"Isi folder templates yang ditemukan: {files_in_templates}")
|
| 55 |
-
else:
|
| 56 |
-
print("Folder 'templates' TIDAK DITEMUKAN oleh aplikasi.")
|
| 57 |
-
print("--- AKHIR DEBUGGING INFO ---")
|
| 58 |
-
# --- Akhir dari kode debugging ---
|
| 59 |
-
|
| 60 |
-
session.pop("chat_history", None)
|
| 61 |
return render_template('index.html')
|
| 62 |
|
| 63 |
@app.route('/get', methods=['GET'])
|
| 64 |
def get_response():
|
| 65 |
-
if not llm
|
| 66 |
-
return jsonify({"error": "Server belum siap.
|
| 67 |
|
| 68 |
user_message = request.args.get('msg')
|
| 69 |
if not user_message:
|
| 70 |
return jsonify({"error": "Pesan tidak boleh kosong."}), 400
|
| 71 |
-
|
| 72 |
-
# Mengambil riwayat chat dari sesi dan mengubahnya ke format yang benar
|
| 73 |
-
chat_history_from_session = session.get("chat_history", [])
|
| 74 |
-
chat_history = []
|
| 75 |
-
for msg in chat_history_from_session:
|
| 76 |
-
if msg.get("sender") == "user":
|
| 77 |
-
chat_history.append(HumanMessage(content=msg["message"]))
|
| 78 |
-
elif msg.get("sender") == "ai":
|
| 79 |
-
chat_history.append(AIMessage(content=msg["message"]))
|
| 80 |
-
|
| 81 |
-
# 1. Prompt untuk membuat pertanyaan baru yang kontekstual
|
| 82 |
-
contextualize_q_prompt = ChatPromptTemplate.from_messages([
|
| 83 |
-
("system", "Mengingat riwayat percakapan dan pertanyaan terbaru, formulasikan ulang pertanyaan menjadi pertanyaan yang berdiri sendiri."),
|
| 84 |
-
MessagesPlaceholder("chat_history"),
|
| 85 |
-
("human", "{input}"),
|
| 86 |
-
])
|
| 87 |
-
history_aware_retriever = create_history_aware_retriever(
|
| 88 |
-
llm, retriever, contextualize_q_prompt
|
| 89 |
-
)
|
| 90 |
-
|
| 91 |
-
# 2. Prompt utama untuk menjawab pertanyaan berdasarkan konteks dari PDF
|
| 92 |
-
qa_prompt = ChatPromptTemplate.from_messages([
|
| 93 |
-
("system", "Anda adalah asisten AI untuk BPVP Kota Sorong. Gunakan potongan konteks berikut untuk menjawab pertanyaan. Jika tidak tahu jawabannya, katakan saja Anda tidak tahu atau arahkan saja ke Website Resmi BPVP Sorong https://bpvpsorong.kemnaker.go.id/web. Jawab dalam bahasa Indonesia.\n\nKonteks:\n{context}"),
|
| 94 |
-
MessagesPlaceholder("chat_history"),
|
| 95 |
-
("human", "{input}"),
|
| 96 |
-
])
|
| 97 |
-
|
| 98 |
-
# Membuat chain untuk menggabungkan dokumen/konteks
|
| 99 |
-
question_answer_chain = create_stuff_documents_chain(llm, qa_prompt)
|
| 100 |
-
|
| 101 |
-
# Menggabungkan semuanya menjadi satu alur RAG (Retrieval-Augmented Generation)
|
| 102 |
-
rag_chain = create_retrieval_chain(history_aware_retriever, question_answer_chain)
|
| 103 |
-
|
| 104 |
try:
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
answer = response.get("answer", "Maaf, saya tidak dapat menemukan jawaban untuk itu.")
|
| 108 |
-
|
| 109 |
-
# Menyimpan percakapan baru ke dalam sesi dalam format JSON
|
| 110 |
-
new_history = session.get("chat_history", [])
|
| 111 |
-
new_history.append({"sender": "user", "message": user_message})
|
| 112 |
-
new_history.append({"sender": "ai", "message": answer})
|
| 113 |
-
session["chat_history"] = new_history
|
| 114 |
-
|
| 115 |
return jsonify(answer)
|
| 116 |
-
|
| 117 |
except Exception as e:
|
| 118 |
-
print(f"GALAT saat
|
| 119 |
-
return jsonify({"error": "Maaf, terjadi masalah
|
| 120 |
-
|
| 121 |
-
@app.route('/load_history', methods=['GET'])
|
| 122 |
-
def load_history():
|
| 123 |
-
return jsonify(session.get("chat_history", []))
|
| 124 |
-
|
| 125 |
-
@app.route('/clear_history', methods=['POST'])
|
| 126 |
-
def clear_history():
|
| 127 |
-
session.pop("chat_history", None)
|
| 128 |
-
return jsonify({"status": "success"})
|
| 129 |
|
| 130 |
if __name__ == '__main__':
|
| 131 |
-
app.run(debug=True)
|
| 132 |
-
|
|
|
|
| 1 |
+
from flask import Flask, render_template, request, jsonify
|
| 2 |
from langchain_google_genai import ChatGoogleGenerativeAI
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3 |
from dotenv import load_dotenv
|
| 4 |
import os
|
| 5 |
|
|
|
|
| 6 |
load_dotenv()
|
| 7 |
|
| 8 |
app = Flask(__name__, template_folder='templates')
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
llm = None
|
|
|
|
| 10 |
|
| 11 |
try:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
llm = ChatGoogleGenerativeAI(model="gemini-1.5-flash", temperature=0.2)
|
| 13 |
print("Model AI (Gemini) berhasil diinisialisasi.")
|
| 14 |
except Exception as e:
|
| 15 |
print(f"GALAT PENTING: Gagal menginisialisasi model Gemini: {e}")
|
|
|
|
|
|
|
|
|
|
| 16 |
|
| 17 |
@app.route('/')
|
| 18 |
def home():
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
return render_template('index.html')
|
| 20 |
|
| 21 |
@app.route('/get', methods=['GET'])
|
| 22 |
def get_response():
|
| 23 |
+
if not llm:
|
| 24 |
+
return jsonify({"error": "Server belum siap. Model AI tidak terinisialisasi."}), 503
|
| 25 |
|
| 26 |
user_message = request.args.get('msg')
|
| 27 |
if not user_message:
|
| 28 |
return jsonify({"error": "Pesan tidak boleh kosong."}), 400
|
| 29 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
try:
|
| 31 |
+
response = llm.invoke(user_message)
|
| 32 |
+
answer = response.content
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
return jsonify(answer)
|
|
|
|
| 34 |
except Exception as e:
|
| 35 |
+
print(f"GALAT saat memanggil LLM: {e}")
|
| 36 |
+
return jsonify({"error": "Maaf, terjadi masalah saat memproses permintaan Anda."}), 500
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
|
| 38 |
if __name__ == '__main__':
|
| 39 |
+
app.run(debug=True, host='0.0.0.0', port=7860)
|
|
|