Bima Ardhia commited on
Commit
57cc744
·
1 Parent(s): 91361f1
.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
+ }