Spaces:
Sleeping
Sleeping
Bima Ardhia commited on
Commit ·
57cc744
1
Parent(s): 91361f1
init
Browse files- .devcontainer/devcontainer.json +33 -0
- .env +9 -0
- .gitignore +1 -0
- Pipfile +20 -0
- Pipfile.lock +0 -0
- __pycache__/api.cpython-311.pyc +0 -0
- __pycache__/api_mage_x.cpython-310.pyc +0 -0
- agent/__pycache__/retrive_agent.cpython-310.pyc +0 -0
- agent/__pycache__/retrive_agent.cpython-311.pyc +0 -0
- agent/retrive_agent.py +97 -0
- api/api_mage_x.py +155 -0
- app/main.py +154 -0
- app/ui.py +67 -0
- mage-442005-26c159b79c30.json +13 -0
- recommendation-system-mage-firebase-adminsdk-ds1lw-1ac94ba6dd.json +13 -0
- tools/__pycache__/retrive.cpython-310.pyc +0 -0
- tools/__pycache__/retrive.cpython-311.pyc +0 -0
- tools/retrive.py +73 -0
- vercel.json +24 -0
.devcontainer/devcontainer.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"name": "Python 3",
|
| 3 |
+
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
|
| 4 |
+
"image": "mcr.microsoft.com/devcontainers/python:1-3.11-bullseye",
|
| 5 |
+
"customizations": {
|
| 6 |
+
"codespaces": {
|
| 7 |
+
"openFiles": [
|
| 8 |
+
"README.md",
|
| 9 |
+
"main.py"
|
| 10 |
+
]
|
| 11 |
+
},
|
| 12 |
+
"vscode": {
|
| 13 |
+
"settings": {},
|
| 14 |
+
"extensions": [
|
| 15 |
+
"ms-python.python",
|
| 16 |
+
"ms-python.vscode-pylance"
|
| 17 |
+
]
|
| 18 |
+
}
|
| 19 |
+
},
|
| 20 |
+
"updateContentCommand": "[ -f packages.txt ] && sudo apt update && sudo apt upgrade -y && sudo xargs apt install -y <packages.txt; [ -f requirements.txt ] && pip3 install --user -r requirements.txt; pip3 install --user streamlit; echo '✅ Packages installed and Requirements met'",
|
| 21 |
+
"postAttachCommand": {
|
| 22 |
+
"server": "streamlit run main.py --server.enableCORS false --server.enableXsrfProtection false"
|
| 23 |
+
},
|
| 24 |
+
"portsAttributes": {
|
| 25 |
+
"8501": {
|
| 26 |
+
"label": "Application",
|
| 27 |
+
"onAutoForward": "openPreview"
|
| 28 |
+
}
|
| 29 |
+
},
|
| 30 |
+
"forwardPorts": [
|
| 31 |
+
8501
|
| 32 |
+
]
|
| 33 |
+
}
|
.env
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
OPENAI_API_KEY="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"
|
| 2 |
+
LANGCHAIN_TRACING_V2=true
|
| 3 |
+
LANGCHAIN_ENDPOINT="https://api.smith.langchain.com"
|
| 4 |
+
LANGCHAIN_API_KEY="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"
|
| 5 |
+
LANGCHAIN_PROJECT="langchain_udemy_k"
|
| 6 |
+
INDEX_NAME="langchain_udemy_k-index"
|
| 7 |
+
PINECONE_API_KEY="37d0996a-8a8a-4792-b29b-f2f78e7f1df2"
|
| 8 |
+
HF_TOKEN="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"
|
| 9 |
+
GROQ_API_KEY="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"
|
.gitignore
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
.vercel
|
Pipfile
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[[source]]
|
| 2 |
+
url = "https://pypi.org/simple"
|
| 3 |
+
verify_ssl = true
|
| 4 |
+
name = "pypi"
|
| 5 |
+
|
| 6 |
+
[packages]
|
| 7 |
+
python-dotenv = "*"
|
| 8 |
+
langchain = "*"
|
| 9 |
+
langchain_openai = "*"
|
| 10 |
+
pinecone-client = "*"
|
| 11 |
+
langchain-pinecone = "*"
|
| 12 |
+
langchain-google-firestore = "*"
|
| 13 |
+
firebase-admin = "*"
|
| 14 |
+
streamlit = "*"
|
| 15 |
+
langchain-community = "*"
|
| 16 |
+
|
| 17 |
+
[dev-packages]
|
| 18 |
+
|
| 19 |
+
[requires]
|
| 20 |
+
python_version = "3.11"
|
Pipfile.lock
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
__pycache__/api.cpython-311.pyc
ADDED
|
Binary file (5.53 kB). View file
|
|
|
__pycache__/api_mage_x.cpython-310.pyc
ADDED
|
Binary file (3.21 kB). View file
|
|
|
agent/__pycache__/retrive_agent.cpython-310.pyc
ADDED
|
Binary file (4.79 kB). View file
|
|
|
agent/__pycache__/retrive_agent.cpython-311.pyc
ADDED
|
Binary file (6.1 kB). View file
|
|
|
agent/retrive_agent.py
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from dotenv import load_dotenv
|
| 2 |
+
from typing import Any, Dict, List
|
| 3 |
+
|
| 4 |
+
load_dotenv()
|
| 5 |
+
from langchain_openai import ChatOpenAI
|
| 6 |
+
from langchain.prompts.prompt import PromptTemplate
|
| 7 |
+
from langchain_core.tools import Tool
|
| 8 |
+
from langchain.agents import (
|
| 9 |
+
create_react_agent,
|
| 10 |
+
AgentExecutor,
|
| 11 |
+
)
|
| 12 |
+
from langchain import hub
|
| 13 |
+
from tools.retrive import retrieve_berita, retrieve_umkm, retrieve_wisata, get_current_time, retrieve_wikipedia_info
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
def run_llm(query: str, chat_history: List[Dict[str, Any]] = []) -> str:
|
| 17 |
+
llm = ChatOpenAI(
|
| 18 |
+
temperature=0,
|
| 19 |
+
model_name="gpt-4o-mini",
|
| 20 |
+
)
|
| 21 |
+
template = """
|
| 22 |
+
Anda adalah asisten yang memiliki akses ke beberapa alat untuk mengambil informasi terbaru di Surabaya. Berdasarkan pertanyaan berikut, gunakan alat yang sesuai untuk memberikan jawaban yang paling akurat dan terkini.
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
Jika pertanyaan pengguna menyebutkan "hari ini", "waktu sekarang", atau "sekarang", gunakan alat Get Current Time untuk mendapatkan waktu saat ini. Ganti kata tersebut dengan waktu yang diperoleh untuk memberikan jawaban yang lebih spesifik.
|
| 26 |
+
|
| 27 |
+
Jika pertanyaan pengguna mengandung kata "terdekat", "dekat sini", atau "di sekitar", gunakan alat Get User Location Name untuk mengambil nama lokasi pengguna saat ini. Ganti kata "terdekat" dengan nama lokasi yang dihasilkan agar jawaban lebih relevan.
|
| 28 |
+
|
| 29 |
+
Setiap kali Anda mengambil data menggunakan alat **Retrieve Berita**, **Retrieve UMKM**, atau **Retrieve Wisata**, pastikan untuk menyertakan **metadata ID dari Firebase** sebagai bagian dari jawaban. Metadata ini dapat digunakan sebagai tautan yang mengarahkan pengguna ke halaman terkait. Format tautan adalah sebagai berikut:
|
| 30 |
+
|
| 31 |
+
- Untuk berita: `https://firebaseapp.com/berita/id`
|
| 32 |
+
- Untuk UMKM: `https://firebaseapp.com/umkm/id`
|
| 33 |
+
- Untuk wisata: `https://firebaseapp.com/wisata/id`
|
| 34 |
+
|
| 35 |
+
Pertanyaan Pengguna: {query}
|
| 36 |
+
|
| 37 |
+
Anda dapat memilih di antara alat berikut:
|
| 38 |
+
1. **Get Current Time** - Untuk mengetahui waktu saat ini dalam format YYYY-MM-DD HH:MM:SS.
|
| 39 |
+
2. **Retrieve Berita** - Untuk mengambil artikel berita terbaru atau informasi terkait peristiwa terkini di Surabaya.
|
| 40 |
+
3. **Retrieve UMKM** - Untuk mendapatkan informasi tentang UMKM, terutama yang terkait makanan lokal dan rekomendasi tempat usaha mikro di Surabaya.
|
| 41 |
+
4. **Retrieve Wisata** - Untuk memberikan detail tentang tempat wisata, atraksi, dan rekomendasi destinasi di Surabaya.
|
| 42 |
+
5. **Wikipedia Search** - Untuk mendapatkan informasi umum dari Wikipedia yang terkait dengan topik atau orang terkenal di luar cakupan lokal.
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
**Instruksi**:
|
| 46 |
+
1. Periksa apakah pertanyaan memerlukan informasi waktu saat ini. Jika ya, gunakan **Get Current Time** terlebih dahulu.
|
| 47 |
+
2. Ganti kata "hari ini" dalam pertanyaan dengan waktu yang diperoleh dari alat **Get Current Time**.
|
| 48 |
+
3. Gunakan alat yang paling sesuai dengan pertanyaan setelah mengganti waktu (jika diperlukan).
|
| 49 |
+
4. Untuk setiap hasil dari **Retrieve Berita**, **Retrieve UMKM**, atau **Retrieve Wisata**, sertakan metadata ID sebagai tautan dalam format di atas, sehingga pengguna dapat membuka halaman terkait.
|
| 50 |
+
5. Berikan jawaban yang akurat, singkat, dan relevan berdasarkan informasi yang ditemukan dari alat tersebut.
|
| 51 |
+
|
| 52 |
+
Mulai menjawab sekarang:
|
| 53 |
+
"""
|
| 54 |
+
prompt_template = PromptTemplate(
|
| 55 |
+
template=template, input_variables=["query"]
|
| 56 |
+
)
|
| 57 |
+
tools_for_agent = [
|
| 58 |
+
Tool(
|
| 59 |
+
name="Retrieve Berita",
|
| 60 |
+
func=retrieve_berita,
|
| 61 |
+
description="Mengambil artikel berita terbaru dan konten yang relevan dengan pertanyaan pengguna, memastikan jawaban yang diberikan selalu terbaru dan informatif mengenai peristiwa terkini."
|
| 62 |
+
),
|
| 63 |
+
Tool(
|
| 64 |
+
name="Retrieve UMKM",
|
| 65 |
+
func=retrieve_umkm,
|
| 66 |
+
description="Mengambil informasi tentang UMKM (usaha mikro, kecil, dan menengah), khususnya yang berkaitan dengan makanan, berdasarkan pertanyaan spesifik, berguna untuk memberikan detail tentang bisnis lokal, kewirausahaan, dan rekomendasi makanan lokal."
|
| 67 |
+
),
|
| 68 |
+
Tool(
|
| 69 |
+
name="Retrieve Wisata",
|
| 70 |
+
func=retrieve_wisata,
|
| 71 |
+
description="Mengambil informasi terkait pariwisata, termasuk tempat wisata seperti pantai, laut, mall, dan atraksi lainnya, serta tips perjalanan, berdasarkan pertanyaan pengguna untuk meningkatkan rekomendasi yang berhubungan dengan pariwisata."
|
| 72 |
+
),
|
| 73 |
+
Tool(
|
| 74 |
+
name="Get Current Time",
|
| 75 |
+
func=get_current_time,
|
| 76 |
+
description="Mengembalikan waktu saat ini dalam format yang mudah dibaca (YYYY-MM-DD HH:MM:SS), membantu untuk menjawab pertanyaan yang memerlukan konteks waktu saat ini."
|
| 77 |
+
),
|
| 78 |
+
Tool(
|
| 79 |
+
name="Wikipedia Search",
|
| 80 |
+
func=retrieve_wikipedia_info,
|
| 81 |
+
description="Mengambil informasi dari Wikipedia mengenai topik umum atau tokoh terkenal. Cocok digunakan untuk menjawab pertanyaan tentang subjek di luar cakupan lokal."
|
| 82 |
+
),
|
| 83 |
+
]
|
| 84 |
+
|
| 85 |
+
react_prompt = hub.pull("hwchase17/react-chat")
|
| 86 |
+
agent = create_react_agent(llm=llm, tools=tools_for_agent, prompt=react_prompt)
|
| 87 |
+
agent_executor = AgentExecutor(agent=agent, tools=tools_for_agent, verbose=True)
|
| 88 |
+
|
| 89 |
+
result = agent_executor.invoke(
|
| 90 |
+
input={
|
| 91 |
+
"input": prompt_template.format(query=query),
|
| 92 |
+
"chat_history": chat_history # Include an empty chat history
|
| 93 |
+
}
|
| 94 |
+
)
|
| 95 |
+
|
| 96 |
+
return result["output"]
|
| 97 |
+
|
api/api_mage_x.py
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from fastapi import FastAPI, HTTPException, File, UploadFile
|
| 2 |
+
from pydantic import BaseModel
|
| 3 |
+
from firebase_admin import credentials, firestore
|
| 4 |
+
from langchain_google_firestore import FirestoreChatMessageHistory
|
| 5 |
+
from langchain.memory import ConversationBufferWindowMemory
|
| 6 |
+
from langchain.schema import HumanMessage, AIMessage
|
| 7 |
+
from dotenv import load_dotenv
|
| 8 |
+
from google.oauth2 import service_account
|
| 9 |
+
from googleapiclient.discovery import build
|
| 10 |
+
from googleapiclient.http import MediaFileUpload
|
| 11 |
+
from fastapi.middleware.cors import CORSMiddleware
|
| 12 |
+
import uuid
|
| 13 |
+
import os
|
| 14 |
+
import tempfile
|
| 15 |
+
import firebase_admin
|
| 16 |
+
from agent.retrive_agent import run_llm
|
| 17 |
+
|
| 18 |
+
# Load environment variables
|
| 19 |
+
load_dotenv()
|
| 20 |
+
|
| 21 |
+
# Initialize FastAPI
|
| 22 |
+
app = FastAPI()
|
| 23 |
+
|
| 24 |
+
# Add CORS Middleware
|
| 25 |
+
app.add_middleware(
|
| 26 |
+
CORSMiddleware,
|
| 27 |
+
allow_origins=["*"], # Gantilah "*" dengan URL spesifik jika perlu
|
| 28 |
+
allow_credentials=True,
|
| 29 |
+
allow_methods=["*"],
|
| 30 |
+
allow_headers=["*"],
|
| 31 |
+
)
|
| 32 |
+
|
| 33 |
+
# Initialize Firebase
|
| 34 |
+
PROJECT_ID = "recommendation-system-mage"
|
| 35 |
+
COLLECTION_NAME = "data_user"
|
| 36 |
+
if not firebase_admin._apps:
|
| 37 |
+
cred = credentials.Certificate("../recommendation-system-mage-firebase-adminsdk-ds1lw-1ac94ba6dd.json")
|
| 38 |
+
firebase_admin.initialize_app(cred)
|
| 39 |
+
client = firestore.client()
|
| 40 |
+
|
| 41 |
+
# Initialize Google Drive API
|
| 42 |
+
SERVICE_ACCOUNT_FILE = '../mage-442005-26c159b79c30.json'
|
| 43 |
+
FOLDER_ID = '1SUjdlLkt58srCwSffDMAoZJKpzPCWszn'
|
| 44 |
+
creds = service_account.Credentials.from_service_account_file(SERVICE_ACCOUNT_FILE)
|
| 45 |
+
drive_service = build('drive', 'v3', credentials=creds)
|
| 46 |
+
|
| 47 |
+
# Define data models
|
| 48 |
+
class ChatRequest(BaseModel):
|
| 49 |
+
user_id: str
|
| 50 |
+
prompt: str
|
| 51 |
+
|
| 52 |
+
class NewSessionRequest(BaseModel):
|
| 53 |
+
user_id: str
|
| 54 |
+
|
| 55 |
+
# Endpoint to check if API is running
|
| 56 |
+
@app.get("/")
|
| 57 |
+
async def check():
|
| 58 |
+
return "API redi bolo!"
|
| 59 |
+
|
| 60 |
+
# Endpoint to initialize a new chat session
|
| 61 |
+
@app.post("/initialize_session")
|
| 62 |
+
def initialize_session(request: NewSessionRequest):
|
| 63 |
+
user_doc_ref = client.collection(COLLECTION_NAME).document(request.user_id)
|
| 64 |
+
user_doc = user_doc_ref.get()
|
| 65 |
+
|
| 66 |
+
if not user_doc.exists:
|
| 67 |
+
raise HTTPException(status_code=404, detail="User ID not found in Firebase.")
|
| 68 |
+
|
| 69 |
+
# Create new session
|
| 70 |
+
session_id = str(uuid.uuid4())
|
| 71 |
+
user_doc_ref.set({"last_session_id": session_id}, merge=True)
|
| 72 |
+
user_doc_ref.collection("message_history").document(session_id).set({})
|
| 73 |
+
|
| 74 |
+
return {"session_id": session_id}
|
| 75 |
+
|
| 76 |
+
# Endpoint to handle chat requests
|
| 77 |
+
@app.post("/chat")
|
| 78 |
+
def chat(request: ChatRequest):
|
| 79 |
+
user_doc_ref = client.collection(COLLECTION_NAME).document(request.user_id)
|
| 80 |
+
user_doc = user_doc_ref.get()
|
| 81 |
+
|
| 82 |
+
if not user_doc.exists:
|
| 83 |
+
raise HTTPException(status_code=404, detail="User ID not found in Firebase.")
|
| 84 |
+
|
| 85 |
+
# Corrected session ID retrieval
|
| 86 |
+
session_id = user_doc.get("last_session_id") if user_doc.exists and "last_session_id" in user_doc.to_dict() else str(uuid.uuid4())
|
| 87 |
+
user_doc_ref.set({"last_session_id": session_id}, merge=True)
|
| 88 |
+
|
| 89 |
+
# Initialize chat history and memory
|
| 90 |
+
chat_history = FirestoreChatMessageHistory(
|
| 91 |
+
session_id=session_id,
|
| 92 |
+
collection=f"{COLLECTION_NAME}/{request.user_id}/message_history",
|
| 93 |
+
client=client,
|
| 94 |
+
)
|
| 95 |
+
memory = ConversationBufferWindowMemory(k=5, chat_memory=chat_history)
|
| 96 |
+
|
| 97 |
+
# Generate response
|
| 98 |
+
generated_response = run_llm(query=request.prompt, chat_history=memory.chat_memory.messages)
|
| 99 |
+
generated_response = generated_response.replace("```", "").strip()
|
| 100 |
+
memory.save_context({"input": request.prompt}, {"output": generated_response})
|
| 101 |
+
|
| 102 |
+
return {"response": generated_response, "session_id": session_id}
|
| 103 |
+
|
| 104 |
+
# Endpoint to get chat history for a session
|
| 105 |
+
@app.get("/chat_history/{user_id}/{session_id}")
|
| 106 |
+
def get_chat_history(user_id: str, session_id: str):
|
| 107 |
+
chat_history = FirestoreChatMessageHistory(
|
| 108 |
+
session_id=session_id,
|
| 109 |
+
collection=f"{COLLECTION_NAME}/{user_id}/message_history",
|
| 110 |
+
client=client,
|
| 111 |
+
)
|
| 112 |
+
messages = [{"role": "user" if isinstance(msg, HumanMessage) else "assistant", "content": msg.content} for msg in chat_history.messages]
|
| 113 |
+
return {"chat_history": messages}
|
| 114 |
+
|
| 115 |
+
# Fungsi untuk mengunggah file ke Google Drive
|
| 116 |
+
def upload_to_drive(file_path: str, folder_id: str) -> str:
|
| 117 |
+
file_name = os.path.basename(file_path)
|
| 118 |
+
file_metadata = {
|
| 119 |
+
'name': file_name,
|
| 120 |
+
'parents': [folder_id]
|
| 121 |
+
}
|
| 122 |
+
media = MediaFileUpload(file_path, resumable=True)
|
| 123 |
+
uploaded_file = drive_service.files().create(
|
| 124 |
+
body=file_metadata, media_body=media, fields='id'
|
| 125 |
+
).execute()
|
| 126 |
+
|
| 127 |
+
# Mengatur izin agar file dapat diakses secara publik
|
| 128 |
+
permission = {'type': 'anyone', 'role': 'reader'}
|
| 129 |
+
drive_service.permissions().create(fileId=uploaded_file['id'], body=permission).execute()
|
| 130 |
+
|
| 131 |
+
# Menghasilkan tautan publik
|
| 132 |
+
public_url = f"https://drive.google.com/uc?export=view&id={uploaded_file['id']}"
|
| 133 |
+
return public_url
|
| 134 |
+
|
| 135 |
+
# Endpoint to upload a file to Google Drive
|
| 136 |
+
@app.post("/upload/")
|
| 137 |
+
async def upload_file(file: UploadFile = File(...)):
|
| 138 |
+
try:
|
| 139 |
+
# Membuat nama file sementara yang unik
|
| 140 |
+
unique_filename = f"{uuid.uuid4()}_{file.filename}"
|
| 141 |
+
file_path = os.path.join(tempfile.gettempdir(), unique_filename)
|
| 142 |
+
|
| 143 |
+
# Simpan file yang diunggah ke file sistem lokal
|
| 144 |
+
with open(file_path, "wb") as buffer:
|
| 145 |
+
buffer.write(await file.read())
|
| 146 |
+
|
| 147 |
+
# Unggah file ke Google Drive
|
| 148 |
+
public_link = upload_to_drive(file_path, FOLDER_ID)
|
| 149 |
+
|
| 150 |
+
# Hapus file lokal setelah diunggah
|
| 151 |
+
os.remove(file_path)
|
| 152 |
+
|
| 153 |
+
return {"message": "File uploaded successfully", "link": public_link}
|
| 154 |
+
except Exception as e:
|
| 155 |
+
raise HTTPException(status_code=500, detail=str(e))
|
app/main.py
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import streamlit as st
|
| 2 |
+
from firebase_admin import credentials, firestore
|
| 3 |
+
from langchain_google_firestore import FirestoreChatMessageHistory
|
| 4 |
+
from langchain.memory import ConversationBufferWindowMemory
|
| 5 |
+
from langchain.schema import HumanMessage, AIMessage
|
| 6 |
+
from dotenv import load_dotenv
|
| 7 |
+
import firebase_admin
|
| 8 |
+
import uuid
|
| 9 |
+
from agent.retrive_agent import run_llm
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
load_dotenv()
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
PROJECT_ID = "recommendation-system-mage"
|
| 17 |
+
COLLECTION_NAME = "data_user"
|
| 18 |
+
|
| 19 |
+
if not firebase_admin._apps:
|
| 20 |
+
cred = credentials.Certificate("../recommendation-system-mage-firebase-adminsdk-ds1lw-1ac94ba6dd.json")
|
| 21 |
+
firebase_admin.initialize_app(cred)
|
| 22 |
+
|
| 23 |
+
client = firestore.client()
|
| 24 |
+
|
| 25 |
+
# Streamlit UI
|
| 26 |
+
st.title(" Chat SITY")
|
| 27 |
+
|
| 28 |
+
# Login and User ID settings
|
| 29 |
+
st.sidebar.header("Login")
|
| 30 |
+
user_id = st.sidebar.text_input("Enter User ID", value="")
|
| 31 |
+
|
| 32 |
+
# Initialize session state variables if they are not present
|
| 33 |
+
if "user_prompt_history" not in st.session_state:
|
| 34 |
+
st.session_state["user_prompt_history"] = []
|
| 35 |
+
|
| 36 |
+
if "chat_answers_history" not in st.session_state:
|
| 37 |
+
st.session_state["chat_answers_history"] = []
|
| 38 |
+
|
| 39 |
+
if "session_id" not in st.session_state:
|
| 40 |
+
st.session_state.session_id = ""
|
| 41 |
+
|
| 42 |
+
if "current_user" not in st.session_state:
|
| 43 |
+
st.session_state.current_user = ""
|
| 44 |
+
|
| 45 |
+
# Check if the user exists in Firebase
|
| 46 |
+
if user_id:
|
| 47 |
+
# If the user has changed, reset the session state
|
| 48 |
+
if st.session_state.current_user != user_id:
|
| 49 |
+
st.session_state.current_user = user_id
|
| 50 |
+
st.session_state.user_prompt_history = []
|
| 51 |
+
st.session_state.chat_answers_history = []
|
| 52 |
+
st.session_state.session_id = ""
|
| 53 |
+
|
| 54 |
+
user_doc_ref = client.collection(COLLECTION_NAME).document(user_id)
|
| 55 |
+
user_doc = user_doc_ref.get()
|
| 56 |
+
if not user_doc.exists:
|
| 57 |
+
st.sidebar.error("Login failed: User ID not found in Firebase.")
|
| 58 |
+
else:
|
| 59 |
+
# Setup session and history if User ID is provided
|
| 60 |
+
|
| 61 |
+
# Initialize Session ID and store in Firebase if new session
|
| 62 |
+
if not st.session_state.session_id:
|
| 63 |
+
session_id = str(uuid.uuid4())
|
| 64 |
+
st.session_state.session_id = session_id
|
| 65 |
+
user_doc_ref.set({"last_session_id": session_id}, merge=True)
|
| 66 |
+
user_doc_ref.collection("message_history").document(session_id).set({})
|
| 67 |
+
st.sidebar.success(f"New session created: {session_id}")
|
| 68 |
+
|
| 69 |
+
if st.sidebar.button("New Chat"):
|
| 70 |
+
session_id = str(uuid.uuid4())
|
| 71 |
+
st.session_state.session_id = session_id
|
| 72 |
+
user_doc_ref.set({"last_session_id": session_id}, merge=True)
|
| 73 |
+
user_doc_ref.collection("message_history").document(session_id).set({})
|
| 74 |
+
st.session_state.user_prompt_history = []
|
| 75 |
+
st.session_state.chat_answers_history = []
|
| 76 |
+
st.sidebar.success(f"New session created: {session_id}")
|
| 77 |
+
|
| 78 |
+
sessions_collection_ref = user_doc_ref.collection("message_history").list_documents()
|
| 79 |
+
session_ids = [session.id for session in sessions_collection_ref]
|
| 80 |
+
|
| 81 |
+
st.sidebar.subheader("Session History")
|
| 82 |
+
selected_session_id = st.sidebar.selectbox("Select a session", session_ids, index=session_ids.index(st.session_state.session_id) if session_ids else -1)
|
| 83 |
+
|
| 84 |
+
# Load chat history when a new session is selected
|
| 85 |
+
if selected_session_id and selected_session_id != st.session_state.session_id:
|
| 86 |
+
st.session_state.session_id = selected_session_id
|
| 87 |
+
|
| 88 |
+
# Load the chat history for the selected session
|
| 89 |
+
chat_history = FirestoreChatMessageHistory(
|
| 90 |
+
session_id=st.session_state.session_id,
|
| 91 |
+
collection=f"{COLLECTION_NAME}/{user_id}/message_history",
|
| 92 |
+
client=client,
|
| 93 |
+
)
|
| 94 |
+
|
| 95 |
+
# Load chat messages into session state variables
|
| 96 |
+
st.session_state["user_prompt_history"] = []
|
| 97 |
+
st.session_state["chat_answers_history"] = []
|
| 98 |
+
|
| 99 |
+
for msg in chat_history.messages:
|
| 100 |
+
if isinstance(msg, HumanMessage):
|
| 101 |
+
st.session_state["user_prompt_history"].append(msg.content)
|
| 102 |
+
elif isinstance(msg, AIMessage):
|
| 103 |
+
st.session_state["chat_answers_history"].append(msg.content)
|
| 104 |
+
|
| 105 |
+
# Display the loaded chat history
|
| 106 |
+
if st.session_state.get("user_prompt_history") and st.session_state.get("chat_answers_history"):
|
| 107 |
+
for user_prompt, answer in zip(st.session_state["user_prompt_history"], st.session_state["chat_answers_history"]):
|
| 108 |
+
st.chat_message("user").write(user_prompt)
|
| 109 |
+
st.chat_message("assistant").write(answer)
|
| 110 |
+
|
| 111 |
+
|
| 112 |
+
|
| 113 |
+
|
| 114 |
+
# Initialize Firestore Chat Message History in user's subcollection
|
| 115 |
+
chat_history = FirestoreChatMessageHistory(
|
| 116 |
+
session_id=st.session_state.session_id,
|
| 117 |
+
collection=f"{COLLECTION_NAME}/{user_id}/message_history",
|
| 118 |
+
client=client,
|
| 119 |
+
)
|
| 120 |
+
|
| 121 |
+
# Initialize memory to store messages specific to the current user and session
|
| 122 |
+
memory = ConversationBufferWindowMemory(
|
| 123 |
+
k=5,
|
| 124 |
+
chat_memory=chat_history
|
| 125 |
+
)
|
| 126 |
+
|
| 127 |
+
# Chatbot UI - Input and Chat Messages
|
| 128 |
+
if prompt := st.chat_input("Enter your prompt here..."):
|
| 129 |
+
with st.spinner("Generating response..."):
|
| 130 |
+
# Use Firebase history in RAG query specific to the current session
|
| 131 |
+
generated_response = run_llm(query=prompt, chat_history=memory.chat_memory.messages)
|
| 132 |
+
generated_response = generated_response.replace("```", "").strip()
|
| 133 |
+
memory.save_context(
|
| 134 |
+
{"input": prompt},
|
| 135 |
+
{"output": generated_response}
|
| 136 |
+
)
|
| 137 |
+
|
| 138 |
+
# Update session state
|
| 139 |
+
st.session_state["user_prompt_history"].append(prompt)
|
| 140 |
+
st.session_state["chat_answers_history"].append(generated_response)
|
| 141 |
+
|
| 142 |
+
# Display the updated chat history
|
| 143 |
+
st.chat_message("user").write(prompt)
|
| 144 |
+
st.chat_message("assistant").write(generated_response)
|
| 145 |
+
else:
|
| 146 |
+
if len(st.session_state["user_prompt_history"]) == 0 and len(st.session_state["chat_answers_history"]) == 0:
|
| 147 |
+
col1, col2, col3 = st.columns([1, 2, 1]) # Membagi halaman menjadi 3 bagian, dengan bagian tengah lebih besar
|
| 148 |
+
with col2:
|
| 149 |
+
st.write("#")
|
| 150 |
+
st.write("#")
|
| 151 |
+
st.write("### Ada yang bisa saya bantu?")
|
| 152 |
+
|
| 153 |
+
else:
|
| 154 |
+
st.sidebar.warning("Please enter your User ID to proceed.")
|
app/ui.py
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# streamlit_ui.py
|
| 2 |
+
|
| 3 |
+
import streamlit as st
|
| 4 |
+
import requests
|
| 5 |
+
|
| 6 |
+
# Backend URL
|
| 7 |
+
API_BASE_URL = "http://127.0.0.1:8000/"
|
| 8 |
+
|
| 9 |
+
st.title("Chat SITY - API Client")
|
| 10 |
+
|
| 11 |
+
# User ID Input for Login
|
| 12 |
+
st.sidebar.header("Login")
|
| 13 |
+
user_id = st.sidebar.text_input("Enter User ID", value="")
|
| 14 |
+
|
| 15 |
+
# Initialize session state variables if they are not present
|
| 16 |
+
if "user_prompt_history" not in st.session_state:
|
| 17 |
+
st.session_state["user_prompt_history"] = []
|
| 18 |
+
|
| 19 |
+
if "chat_answers_history" not in st.session_state:
|
| 20 |
+
st.session_state["chat_answers_history"] = []
|
| 21 |
+
|
| 22 |
+
if "session_id" not in st.session_state:
|
| 23 |
+
st.session_state.session_id = ""
|
| 24 |
+
|
| 25 |
+
if user_id:
|
| 26 |
+
# Start a new session if not already initialized
|
| 27 |
+
if not st.session_state.session_id:
|
| 28 |
+
response = requests.post(f"{API_BASE_URL}/initialize_session", json={"user_id": user_id})
|
| 29 |
+
if response.status_code == 200:
|
| 30 |
+
st.session_state.session_id = response.json()["session_id"]
|
| 31 |
+
st.sidebar.success(f"New session created: {st.session_state.session_id}")
|
| 32 |
+
else:
|
| 33 |
+
st.sidebar.error("Login failed: User ID not found in Firebase.")
|
| 34 |
+
|
| 35 |
+
# New Chat Button
|
| 36 |
+
if st.sidebar.button("New Chat"):
|
| 37 |
+
response = requests.post(f"{API_BASE_URL}/initialize_session", json={"user_id": user_id})
|
| 38 |
+
if response.status_code == 200:
|
| 39 |
+
st.session_state.session_id = response.json()["session_id"]
|
| 40 |
+
st.session_state.user_prompt_history = []
|
| 41 |
+
st.session_state.chat_answers_history = []
|
| 42 |
+
st.sidebar.success(f"New session created: {st.session_state.session_id}")
|
| 43 |
+
|
| 44 |
+
# Chat History Retrieval
|
| 45 |
+
if st.session_state.session_id:
|
| 46 |
+
history_response = requests.get(f"{API_BASE_URL}/chat_history/{user_id}/{st.session_state.session_id}")
|
| 47 |
+
if history_response.status_code == 200:
|
| 48 |
+
chat_history = history_response.json()["chat_history"]
|
| 49 |
+
st.session_state.user_prompt_history = [msg["content"] for msg in chat_history if msg["role"] == "user"]
|
| 50 |
+
st.session_state.chat_answers_history = [msg["content"] for msg in chat_history if msg["role"] == "assistant"]
|
| 51 |
+
|
| 52 |
+
# Display chat history
|
| 53 |
+
for user_prompt, answer in zip(st.session_state["user_prompt_history"], st.session_state["chat_answers_history"]):
|
| 54 |
+
st.chat_message("user").write(user_prompt)
|
| 55 |
+
st.chat_message("assistant").write(answer)
|
| 56 |
+
|
| 57 |
+
# Chat Input
|
| 58 |
+
if prompt := st.chat_input("Enter your prompt here..."):
|
| 59 |
+
response = requests.post(f"{API_BASE_URL}/chat", json={"user_id": user_id, "prompt": prompt})
|
| 60 |
+
if response.status_code == 200:
|
| 61 |
+
generated_response = response.json()["response"]
|
| 62 |
+
st.session_state["user_prompt_history"].append(prompt)
|
| 63 |
+
st.session_state["chat_answers_history"].append(generated_response)
|
| 64 |
+
st.chat_message("user").write(prompt)
|
| 65 |
+
st.chat_message("assistant").write(generated_response)
|
| 66 |
+
else:
|
| 67 |
+
st.sidebar.warning("Please enter your User ID to proceed.")
|
mage-442005-26c159b79c30.json
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"type": "service_account",
|
| 3 |
+
"project_id": "mage-442005",
|
| 4 |
+
"private_key_id": "26c159b79c307e8ccd6534080c0195703f04e559",
|
| 5 |
+
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDFbt+8scgZcYdZ\nPx3MsQPvTL7A1LOE2IEErsZP1bXQ/PQA/9c/6K9Ga//Fd61x+ZOnEjZaRdrKh4e7\nNywHxytuJ4LeOyqiiXF5RptOcjRVXWg2I6svytoo5MKQcZ5mTVMnVfUYq/YaX7LY\n0xvgSPS0FJUeTgLt8ncDJMrfsoHrn41+2fLUr6aVzwBTN5Xa+PKSUpUXltR0JXr2\nN0Bb3lCq2Y+/jV8g3Rlz6pYrtuouJadmtXo1/dz7dZuJ2m87+RaZ3n6yx+3nCxmz\nwD4B2P4y/dglvKEYEp7YG99mSQOOtGKsZ6d4FGx74waelfQTOgMyTT4UISt9jKVz\nuS6X8QMJAgMBAAECggEAFGE+jS7Y1e+HJipCvDdljZUhd6w9H7BtmPslk2YfD4Sc\n92FxabJuLVnGnC6fY818dVmG7MibLh7RXvzx+ZeQnx1K//+hhgekA/3K2E0no8wx\njq0d5aAN5vy+LMTdsfe3Zq8TzskpbU2Fm6YnEX7Wa6RYRDmPSdqmeFea7X5ytMyj\n5eV7Vg0T0nIpN8seKecUbgRdbUbqMcZU0tgK4Oxdj03sa+JJJ2r3SIE9g1vtfHG2\nd42mfUI44GHsD7kiXSLQBGgqzOTGxYk4sQa9eeZPDNKXr8UPwypt9ahXYJY/LDyj\nAH+PgyIEdYFhv6UAZXE6u8MlxCPj5pkUGgASCoV9BQKBgQD2VBmjWdTpO/nKh8u9\neK4X07h/j/zd0fq7jJMma5G+nDDemcEOxEe+YFHHB7PHg3MN8a4SeBPxyCvO1wUQ\nSkRqfxFJOzWhgzK1ESPxy5zA1dQ5jUSub6AMvBmuTvy/zHPtd1b3nO1KIFUv8RVB\nu6PBuLClMjhiA2FRV0f6NpOf7wKBgQDNL1DR0ylhOV19xYFXTf/9oYwQ2dGcZHcD\nooW5jotepIg768KC7feavx03j7s0Nhl097E83tjY0v0KIRjgni6hdnxB4HwscI92\nmcbtKrOh8Un+K5tsYvZx3Wgi5y1lFEMitPy0v8+fGjUNUgK4Oonf9PsHyTYsCWbA\naVSOiPcUhwKBgFiwNvrlYQ8IlQsikWyKgsP5argi83w6GfhkyKZQnIzwV3gOC8Bx\nUxNsQoVSdJwk68vddDsaGLQ4ye0S5bPTyYY+cc7YDps0TZF7tmFcWffkBSEjh9L2\nRb3QC78CmWXFCwg4q4tDaPwDYCh+uJSOJoudH5ya1EoVxXgv4K5p8ATpAoGAWhiB\nq3DGRbuzsqtL7PMCCfOqliee48Y1gDIX9++AgRFMBMu0AFvPknKCuMfzEq0Cppqw\nh6Luot6aX51C2DZ9EUb+rsqMm9LdG93QPIm4kM5riCDLwV7/CeaHeHP8OdsY05+X\nKyLiXuFaFDxDl3OU4PMoWzXeBJ4oMSrPBztbCvcCgYEA4qSxCTQYlOCL6uA6ts2U\nwiPbh5y/iY7gq0AnBF6POzBdqKGtFUlabARkCsNYdstYiRbkwCctcQzbX0VYe0zD\ndg7kl/LXbqkvdQHrg7T+pthcAD1Yt9cd3CRkWGVxdPD0IVBjTTDeY/PLjcuTFZJ4\nLr3NXBGKUDrVbByjhUqwPj4=\n-----END PRIVATE KEY-----\n",
|
| 6 |
+
"client_email": "drive-service-account@mage-442005.iam.gserviceaccount.com",
|
| 7 |
+
"client_id": "117806948028026927979",
|
| 8 |
+
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
|
| 9 |
+
"token_uri": "https://oauth2.googleapis.com/token",
|
| 10 |
+
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
|
| 11 |
+
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/drive-service-account%40mage-442005.iam.gserviceaccount.com",
|
| 12 |
+
"universe_domain": "googleapis.com"
|
| 13 |
+
}
|
recommendation-system-mage-firebase-adminsdk-ds1lw-1ac94ba6dd.json
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"type": "service_account",
|
| 3 |
+
"project_id": "recommendation-system-mage",
|
| 4 |
+
"private_key_id": "1ac94ba6dd33936ea62020b6d5054c3271c0c607",
|
| 5 |
+
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCSl+7Qkoh8uNcY\nTQWAoEKyDvXI44rxyCaC9RoM6QJgBrZUBbOjQVePirzTTC3Kk5NtsgdaTPNpjx25\nFn4CF2aHeyOeVhdn1yrdA80FFjOrd3JMSt7barDmhg3VDoRz0dmNM21rTjGYa5wx\nsPpExQw68aEYwyJhRN8EmPdK+I/N19X7D+x/9cVi8pjI+EQvAo0xlz6T2Wchy3pr\ndWkk0E6tD/opR7pyHbaPjOkAAP4A9Uj7ZJhNjTa1SFjoaOY/MOznOoV8QcL6NjMo\nILYLblE4RM8lAOQwpVbzfuDj5u4KLUWxaYUpASIWiz73qaXG4Wg1pCXWqvPIwr9n\nT9YL7wXbAgMBAAECggEAFCC9XzEHgYyFqCYHL+KRVc59C/DGRq1zMD8ELSqfM10o\nkr/Xqv5RTfnANIj8rph1wTWVEd6H+4H1lFDUy2e4IbkUKmzquMzP61nWwDCMtqnn\nbTdIgzsSgAx/ALaGFDsHkn4xs26gm6uG3kHNEz01ETDVLEe6xD1HG+P+7HHVmO8p\nD251I9KYjZp0+ocXMDcpzy9zWKsZLOx7m7rv38PXcfCd3C+UMQ9CIwlJ52shjvrD\n/QiSVHQHr9xx+QOK1N9h1oClrQ6bx6Tr6iXtSDZAZyRnUl5LBXxVSLUjfndp/yyq\nBdRau93LItqxcFqu5da3wIyRe3eZv9dZLNVYzTK2cQKBgQDHYsMJdvuzY4FDaKdw\nvGH2vQQ6vo2PgpdRwJv37bv/QX4i2iLGUUtyUnzw8vaUguk8hH3h6YZ1YTxVVcmo\nrnX9KqoP0riqvu7wDySG95MQ72aD8SAbqPg2UDx5PNxmRNJtxbrGNuS2jh1OAbIe\nb1cE7QIGWJUMYTm4DMInL35GcQKBgQC8N7qkS/CD0T2uggpO+soQ4GOpEAufZ9ny\nETyZUqBRIiP9fluFzF8R+YMML+PSSCQPiu2AYRX8WWflNFOnyGYx0Cbodo+LBE8O\nNWVnuuxfzzJZEFsh1pk0lFcJ/qrQadRJk0e+acR7yZU8R1ejF/BrEjq1luQRqtfg\nC8brQedvCwKBgFrmJbDM89dGyAmpTpzQ5YCNj74QXY1Nphr5SqHvWkP24cCV3kC3\nk0PdY2Sd/9iZDigu5wz1X/1nhRAKelNSpivzJXDtSo9dWKVM4gQ+HmgcHIqOhWrW\nz8JDNi63lmtxeNXezVXMdNzdUXLcxw2lCPEP9FpcTCdGs/+6oVEoD9OhAoGAf6s1\nmNhB7sfxlPt0TppikgwCzdyqZZgmB8KVXlLjl+UWkI4zOpCkNCcRMyUQ3cQ9YaWU\n8C3qod9rT9esnvSaDVPp8GjreRqVHUgu3qu2Rk7fEfa8Ojm8diPg3lC2QORoMPgM\nBCbuNiFIbzjdQy2r0JTu6dnOHgXKpJiYd1+ewn0CgYAXBtFkoiYPn94XDBDxgcdB\nbSxW0Pr4fK9pn3JiU/vvyS29xXkmLLtwZS7ZJ/mhuUNskwYnxqqE5A1Ybji087kX\nfM55KjIBsiRtypID0vO97ZZOZH/3yZAvQxtZ6BU4Gu0J6gPifxJuaGuOOwMpeNZr\nmyqiY3wZOdLXOpHybcorDg==\n-----END PRIVATE KEY-----\n",
|
| 6 |
+
"client_email": "firebase-adminsdk-ds1lw@recommendation-system-mage.iam.gserviceaccount.com",
|
| 7 |
+
"client_id": "112738464264180377678",
|
| 8 |
+
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
|
| 9 |
+
"token_uri": "https://oauth2.googleapis.com/token",
|
| 10 |
+
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
|
| 11 |
+
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-ds1lw%40recommendation-system-mage.iam.gserviceaccount.com",
|
| 12 |
+
"universe_domain": "googleapis.com"
|
| 13 |
+
}
|
tools/__pycache__/retrive.cpython-310.pyc
ADDED
|
Binary file (2.13 kB). View file
|
|
|
tools/__pycache__/retrive.cpython-311.pyc
ADDED
|
Binary file (3.88 kB). View file
|
|
|
tools/retrive.py
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import List, Dict, Any
|
| 2 |
+
from langchain_pinecone import PineconeVectorStore
|
| 3 |
+
from langchain_openai import OpenAIEmbeddings
|
| 4 |
+
from pinecone import Pinecone
|
| 5 |
+
import json
|
| 6 |
+
from datetime import datetime
|
| 7 |
+
from langchain_community.tools import WikipediaQueryRun
|
| 8 |
+
from langchain_community.utilities import WikipediaAPIWrapper
|
| 9 |
+
|
| 10 |
+
# Initialize Pinecone client
|
| 11 |
+
pc = Pinecone(api_key="pcsk_6vVrG6_2ZUYuJwQcrKefGPodrfDuYAXB4AKD2ZENoXF7qmAahuSAYWijPTaBhkkb8DoB4M")
|
| 12 |
+
index = "mage-x-embeddings-all"
|
| 13 |
+
index = pc.Index(index)
|
| 14 |
+
docsearch = PineconeVectorStore(index=index, embedding=OpenAIEmbeddings())
|
| 15 |
+
|
| 16 |
+
# Initialize Wikipedia API Wrapper and Tool
|
| 17 |
+
api_wrapper_wiki = WikipediaAPIWrapper(top_k_results=1, doc_content_chars_max=1000)
|
| 18 |
+
wiki = WikipediaQueryRun(api_wrapper=api_wrapper_wiki)
|
| 19 |
+
|
| 20 |
+
def retrieve_wisata(query: str) -> str:
|
| 21 |
+
"""
|
| 22 |
+
Mengambil teks dan metadata yang relevan dari vector store UMKM berdasarkan query yang diberikan.
|
| 23 |
+
"""
|
| 24 |
+
search_results = docsearch.similarity_search(query, filter={'collection_type': 'data_wisata'})
|
| 25 |
+
retrieved_texts = []
|
| 26 |
+
for result in search_results:
|
| 27 |
+
text = result.page_content
|
| 28 |
+
metadata = result.metadata.get("firebase_id", "")
|
| 29 |
+
retrieved_texts.append({"content": text, "metadata": metadata})
|
| 30 |
+
return json.dumps(retrieved_texts, indent=2)
|
| 31 |
+
|
| 32 |
+
def retrieve_berita(query: str) -> str:
|
| 33 |
+
"""
|
| 34 |
+
Mengambil teks dan metadata yang relevan dari vector store UMKM berdasarkan query yang diberikan.
|
| 35 |
+
"""
|
| 36 |
+
search_results = docsearch.similarity_search(query, filter={'collection_type': 'data_berita'})
|
| 37 |
+
retrieved_texts = []
|
| 38 |
+
for result in search_results:
|
| 39 |
+
text = result.page_content
|
| 40 |
+
metadata = result.metadata.get("firebase_id", "")
|
| 41 |
+
retrieved_texts.append({"content": text, "metadata": metadata})
|
| 42 |
+
return json.dumps(retrieved_texts, indent=2)
|
| 43 |
+
|
| 44 |
+
def retrieve_umkm(query: str) -> str:
|
| 45 |
+
"""
|
| 46 |
+
Mengambil teks dan metadata yang relevan dari vector store UMKM berdasarkan query yang diberikan.
|
| 47 |
+
"""
|
| 48 |
+
search_results = docsearch.similarity_search(query, filter={'collection_type': 'data_umkm'})
|
| 49 |
+
retrieved_texts = []
|
| 50 |
+
for result in search_results:
|
| 51 |
+
text = result.page_content
|
| 52 |
+
metadata = result.metadata.get("firebase_id", "")
|
| 53 |
+
retrieved_texts.append({"content": text, "metadata": metadata})
|
| 54 |
+
return json.dumps(retrieved_texts, indent=2)
|
| 55 |
+
|
| 56 |
+
def retrieve_wikipedia_info(query: str) -> str:
|
| 57 |
+
"""
|
| 58 |
+
Mengambil informasi dari Wikipedia berdasarkan query yang diberikan.
|
| 59 |
+
"""
|
| 60 |
+
result = wiki.run(query) # Menggunakan WikipediaQueryRun untuk menjalankan pencarian
|
| 61 |
+
return result if result else "Tidak ditemukan hasil di Wikipedia."
|
| 62 |
+
|
| 63 |
+
def get_current_time(*args, **kwargs) -> str:
|
| 64 |
+
"""
|
| 65 |
+
Mengembalikan waktu saat ini dalam format yang mudah dibaca.
|
| 66 |
+
"""
|
| 67 |
+
current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
| 68 |
+
return current_time
|
| 69 |
+
|
| 70 |
+
# Contoh penggunaan fungsi baru
|
| 71 |
+
# print(retrieve_umkm("Produk UMKM terbaik?"))
|
| 72 |
+
# print(retrieve_berita("Berita ekonomi terbaru?"))
|
| 73 |
+
# print(retrieve_wisata("Tempat wisata terpopuler?"))
|
vercel.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"version": 2,
|
| 3 |
+
"builds": [
|
| 4 |
+
{
|
| 5 |
+
"src": "api_mage_x.py",
|
| 6 |
+
"use": "@vercel/python",
|
| 7 |
+
"config": {
|
| 8 |
+
"maxLambdaSize": "50mb",
|
| 9 |
+
"pythonVersion": "3.11"
|
| 10 |
+
}
|
| 11 |
+
}
|
| 12 |
+
],
|
| 13 |
+
"routes": [
|
| 14 |
+
{
|
| 15 |
+
"src": "/(.*)",
|
| 16 |
+
"dest": "api_mage_x.py"
|
| 17 |
+
}
|
| 18 |
+
],
|
| 19 |
+
"env": {
|
| 20 |
+
"PROJECT_ID": "recommendation-system-mage",
|
| 21 |
+
"COLLECTION_NAME": "data_user",
|
| 22 |
+
"GOOGLE_APPLICATION_CREDENTIALS": "./recommendation-system-mage-firebase-adminsdk-ds1lw-1ac94ba6dd.json"
|
| 23 |
+
}
|
| 24 |
+
}
|