Spaces:
Sleeping
Sleeping
OnlyBiggg
commited on
Commit
·
d73e455
1
Parent(s):
e7ac3a5
first commit
Browse files- .env +5 -0
- Dockerfile +9 -0
- __pycache__/app.cpython-39.pyc +0 -0
- __pycache__/main.cpython-39.pyc +0 -0
- app/api/__pycache__/routes.cpython-39.pyc +0 -0
- app/api/routes.py +20 -0
- app/core/__pycache__/config.cpython-39.pyc +0 -0
- app/core/config.py +14 -0
- app/data/busbooking-451909-aa92e337868d.json +13 -0
- app/services/__pycache__/service.cpython-39.pyc +0 -0
- app/services/api.py +61 -0
- app/services/service.py +57 -0
- app/types/__pycache__/response.cpython-39.pyc +0 -0
- app/types/response.py +16 -0
- main.py +10 -0
- requirements.txt +39 -0
.env
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
PROJECT_ID = "busbooking-451909"
|
2 |
+
LOCATION = "us-central1"
|
3 |
+
AGENT_ID = "76716506-e80a-413a-931b-6b61ef715d31"
|
4 |
+
LANGUAGE_CODE="vi"
|
5 |
+
GOOGLE_APPLICATION_CREDENTIALS="app/data/busbooking-451909-aa92e337868d.json"
|
Dockerfile
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
FROM python:3.9
|
2 |
+
|
3 |
+
COPY . .
|
4 |
+
|
5 |
+
WORKDIR /
|
6 |
+
|
7 |
+
RUN pip install --no-cache-dir --upgrade -r /requirements.txt
|
8 |
+
|
9 |
+
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7860"]
|
__pycache__/app.cpython-39.pyc
ADDED
Binary file (432 Bytes). View file
|
|
__pycache__/main.cpython-39.pyc
ADDED
Binary file (433 Bytes). View file
|
|
app/api/__pycache__/routes.cpython-39.pyc
ADDED
Binary file (1.04 kB). View file
|
|
app/api/routes.py
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from typing import Optional
|
2 |
+
from fastapi import FastAPI, APIRouter, HTTPException, Request, Response, status
|
3 |
+
from fastapi.responses import JSONResponse, RedirectResponse, HTMLResponse
|
4 |
+
from pydantic import BaseModel
|
5 |
+
|
6 |
+
from app.services.service import chatbot_response
|
7 |
+
from app.types.response import Message, ResponseAPI
|
8 |
+
|
9 |
+
router = APIRouter()
|
10 |
+
|
11 |
+
@router.post("/chat")
|
12 |
+
def chat(message: Message) -> ResponseAPI:
|
13 |
+
session_id = message.session_id
|
14 |
+
message_content = message.message_content
|
15 |
+
data = chatbot_response(session_id, message_content)
|
16 |
+
return ResponseAPI(data=data, status=status.HTTP_200_OK)
|
17 |
+
|
18 |
+
@router.get("/")
|
19 |
+
def home():
|
20 |
+
return "API CHATBOT BUS BOOKING"
|
app/core/__pycache__/config.cpython-39.pyc
ADDED
Binary file (595 Bytes). View file
|
|
app/core/config.py
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
from dotenv import load_dotenv
|
3 |
+
|
4 |
+
load_dotenv() # Load biến môi trường từ file .env
|
5 |
+
|
6 |
+
class Settings:
|
7 |
+
API_BASE_URL = os.getenv("API_BASE_URL") # API gốc (backend dev)
|
8 |
+
PROJECT_ID = os.getenv("PROJECT_ID")
|
9 |
+
LOCATION = os.getenv("LOCATION")
|
10 |
+
AGENT_ID = os.getenv("AGENT_ID")
|
11 |
+
LANGUAGE_CODE = os.getenv("LANGUAGE_CODE")
|
12 |
+
GOOGLE_APPLICATION_CREDENTIALS=os.getenv("GOOGLE_APPLICATION_CREDENTIALS")
|
13 |
+
|
14 |
+
settings = Settings()
|
app/data/busbooking-451909-aa92e337868d.json
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"type": "service_account",
|
3 |
+
"project_id": "busbooking-451909",
|
4 |
+
"private_key_id": "aa92e337868d77340f1e1bc3d0119738f48b8a49",
|
5 |
+
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDwozPFZx+v2DH+\nXFMLaft+4tnaWKPDGEgQ0IGwmXUtgVzd7iuH/fI9tXFiRw1ecFGAzundf1qiJJis\npMgfMxXm5fWpaKa4AM5LKxootKYPLZeJ3/N+BhJkCSmDXZmk6TuBff3WBRUkDj9n\nQTnpRSCBsCxArvm2zw6PSUqHwPiW/g05q6escmHXZUO3wpLgFz41u1Xy7M2Rc/bO\n3j6OYogYxZkp5aY5EpWhUKO2+qNVaVQqDweJhQ7/M+UpX5Va9VdMAM7dm3BUIy1Y\n3c8NDgUvL5uXKljoHrPpGXm+1QZTnrT18y3Jmo5PxkIF0u/SXDnFTYl9CL876ewq\nYaN55d9fAgMBAAECggEAArpm8Nr9cfnqfy6+xkdaUZLy01Xj7WdOEdq7Taw/ttdb\nnSyBE9aeM3LmKS4TCboOQn6WCivSdDoj/PkVR71Fh0ueIGCOW1GvBQ0lC8cYht2G\ndUqzsP8SoE22ScX64vK9+PbbtNxz4+fBckM8C9f7yVyc89LIA/mO+bLkBGv8pYGQ\nNg2Po8Oi8wjA06XMEaFVfrURnyQoUVVeIXBn/L0TViL/vSo0wshYQw9hoXI6RrUW\n1SDjfRmzOIt63R7x4Bn/BZYvgjtRewAL325ooZVXqrzXHZ9yinC/7BIrxQCF9Ncr\nuKok9SDhNES2OUUbO8QlwW4EVvTkiCb59r26jqU26QKBgQD6K2AyZ1u2XRI9HpW3\nsAeshUDcG/Gj0cnWQlpe6hr+UOrMt7LIgOhuQeR1/5EZ/ZLG8FYKE096ffP/2ND8\nG+JzTTj5Fiv9ZzUdKWPQGE5D6TwJmVAO6R8ZaodykkIgg7Thn17og4EbeSAqNtey\nh2LSLnYrT9imjfR78n+vPYCwfQKBgQD2PvRknpN+zMYnMUA/pho0/c7G8kbORiWp\nDpHabHDbtdKSgWC3enQ3bVPSeGiZNvrjSar+1/8H2C3WovhgYTp4o7+IdM2cKWOZ\nJsQNbgoXYgeaylIiwZGRQN0x1q4ho2w3UGxu3spupyFFo8yNRay8JkCI6OMX+ZWd\nG2QXQEOSCwKBgQCrZa55uhC+x9NoJp1DBYqsa3t9knOi3mffsQRDhTdLSFsmOTF3\nZ8JXUDPbmGZsnSvDuwPn0UUh0kuq3XyJTf1/K8g9+C/ZZK2iNipZd12f75sfpHeS\nT6vr+O2l1IkTx8jU0CDxQq/hB8K+yWZMva85+3UgxYrUyetYRFOw131k7QKBgGxc\nt9+viOi75FdK7SMVTWMUbfJOm6oaZGhI6RZdsix9jvS5yn3zfUEG82QjaKRD9ZQf\nzwfmtWwWTdWuUe7X2otMQ/UgsXqPHC1BSfU+/2Ha2c3cStjQpeZtzOkpt+dFq1GM\nKqt/j0WydonW0yU4DBOgIbYeBhF+28APVbSFqzaRAoGBAPRPNNCJcbIsCZEyBgwn\nCgK9W5anZDVmtwXbAVAoKMzzxFVi49W+6Lduw9oeTqgx9J1AdQMwV27I0hcPtfBE\nw5IVhrQsd6dRKDt/CJwEN6/iR9AqLx3T/rO342yOIi9GSPsFISQiiPDywfkNSzj6\nhT0eDw3eRs/RUv0zqcjFUjNI\n-----END PRIVATE KEY-----\n",
|
6 |
+
"client_email": "chatbot@busbooking-451909.iam.gserviceaccount.com",
|
7 |
+
"client_id": "111019976759266480456",
|
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/chatbot%40busbooking-451909.iam.gserviceaccount.com",
|
12 |
+
"universe_domain": "googleapis.com"
|
13 |
+
}
|
app/services/__pycache__/service.cpython-39.pyc
ADDED
Binary file (1.88 kB). View file
|
|
app/services/api.py
ADDED
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import httpx
|
2 |
+
from app.core.config import settings
|
3 |
+
from typing import Optional, Dict, Any
|
4 |
+
|
5 |
+
API_BASE_URL = settings.API_BASE_URL # Lấy base URL từ config
|
6 |
+
|
7 |
+
async def get(endpoint: str, params: Optional[Dict[str, Any]] = None, headers: Optional[Dict[str, str]] = None):
|
8 |
+
"""Gọi API GET"""
|
9 |
+
url = f"{API_BASE_URL}{endpoint}"
|
10 |
+
headers = headers or {}
|
11 |
+
async with httpx.AsyncClient() as client:
|
12 |
+
try:
|
13 |
+
response = await client.get(url, headers=headers, params=params)
|
14 |
+
response.raise_for_status()
|
15 |
+
return response.json()
|
16 |
+
except httpx.HTTPStatusError as http_err:
|
17 |
+
return {"error": f"HTTP {http_err.response.status_code}: {http_err.response.text}"}
|
18 |
+
except Exception as err:
|
19 |
+
return {"error": f"Request failed: {str(err)}"}
|
20 |
+
|
21 |
+
async def post(endpoint: str , payload: Dict[str, Any] = None,headers: Optional[Dict[str, str]] = None):
|
22 |
+
"""Gọi API POST"""
|
23 |
+
url = f"{API_BASE_URL}{endpoint}"
|
24 |
+
headers = headers or {"Content-Type": "application/json"}
|
25 |
+
async with httpx.AsyncClient() as client:
|
26 |
+
try:
|
27 |
+
response = await client.post(url, json=payload, headers=headers)
|
28 |
+
response.raise_for_status()
|
29 |
+
return response.json()
|
30 |
+
except httpx.HTTPStatusError as http_err:
|
31 |
+
return {"error": f"HTTP {http_err.response.status_code}: {http_err.response.text}"}
|
32 |
+
except Exception as err:
|
33 |
+
return {"error": f"Request failed: {str(err)}"}
|
34 |
+
|
35 |
+
async def put_api(endpoint: str, payload: Dict[str, Any], headers: Optional[Dict[str, str]] = None):
|
36 |
+
"""Gọi API PUT"""
|
37 |
+
url = f"{API_BASE_URL}{endpoint}"
|
38 |
+
headers = headers or {"Content-Type": "application/json"}
|
39 |
+
async with httpx.AsyncClient() as client:
|
40 |
+
try:
|
41 |
+
response = await client.put(url, json=payload, headers=headers)
|
42 |
+
response.raise_for_status()
|
43 |
+
return response.json()
|
44 |
+
except httpx.HTTPStatusError as http_err:
|
45 |
+
return {"error": f"HTTP {http_err.response.status_code}: {http_err.response.text}"}
|
46 |
+
except Exception as err:
|
47 |
+
return {"error": f"Request failed: {str(err)}"}
|
48 |
+
|
49 |
+
async def delete_api(endpoint: str, params: Optional[Dict[str, Any]] = None, headers: Optional[Dict[str, str]] = None):
|
50 |
+
"""Gọi API DELETE"""
|
51 |
+
url = f"{API_BASE_URL}{endpoint}"
|
52 |
+
headers = headers or {}
|
53 |
+
async with httpx.AsyncClient() as client:
|
54 |
+
try:
|
55 |
+
response = await client.delete(url, headers=headers, params=params)
|
56 |
+
response.raise_for_status()
|
57 |
+
return response.json()
|
58 |
+
except httpx.HTTPStatusError as http_err:
|
59 |
+
return {"error": f"HTTP {http_err.response.status_code}: {http_err.response.text}"}
|
60 |
+
except Exception as err:
|
61 |
+
return {"error": f"Request failed: {str(err)}"}
|
app/services/service.py
ADDED
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
from dotenv import load_dotenv
|
3 |
+
from google.cloud import dialogflowcx_v3beta1 as dialogflow
|
4 |
+
from google.api_core.client_options import ClientOptions
|
5 |
+
from app.core.config import settings
|
6 |
+
|
7 |
+
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = settings.GOOGLE_APPLICATION_CREDENTIALS
|
8 |
+
PROJECT_ID = settings.PROJECT_ID
|
9 |
+
LOCATION = settings.LOCATION # Vị trí agent của bạn
|
10 |
+
AGENT_ID = settings.AGENT_ID
|
11 |
+
LANGUAGE_CODE = settings.LANGUAGE_CODE
|
12 |
+
|
13 |
+
def chatbot_response(
|
14 |
+
session_id: str,
|
15 |
+
texts: list
|
16 |
+
):
|
17 |
+
"""Gửi văn bản đến Dialogflow CX và nhận phản hồi"""
|
18 |
+
|
19 |
+
endpoint = f"{LOCATION}-dialogflow.googleapis.com"
|
20 |
+
client_options = ClientOptions(api_endpoint=endpoint)
|
21 |
+
client = dialogflow.SessionsClient(client_options=client_options)
|
22 |
+
|
23 |
+
session_path = f"projects/{PROJECT_ID}/locations/{LOCATION}/agents/{AGENT_ID}/sessions/{session_id}"
|
24 |
+
|
25 |
+
extracted_texts = []
|
26 |
+
all_chip_options = []
|
27 |
+
for text in texts:
|
28 |
+
text_input = dialogflow.TextInput(text=text)
|
29 |
+
query_input = dialogflow.QueryInput(text=text_input, language_code=LANGUAGE_CODE)
|
30 |
+
|
31 |
+
request = dialogflow.DetectIntentRequest(
|
32 |
+
session=session_path,
|
33 |
+
query_input=query_input
|
34 |
+
)
|
35 |
+
|
36 |
+
response = client.detect_intent(request=request)
|
37 |
+
query_result = response.query_result
|
38 |
+
|
39 |
+
for message in query_result.response_messages:
|
40 |
+
if hasattr(message, "text") and message.text.text:
|
41 |
+
extracted_texts.extend(message.text.text)
|
42 |
+
|
43 |
+
chip_opttion = []
|
44 |
+
if hasattr(message, "payload") and message.payload:
|
45 |
+
payload_dict = dict(message.payload)
|
46 |
+
if "richContent" in payload_dict:
|
47 |
+
rich_content = payload_dict["richContent"]
|
48 |
+
for item_group in rich_content:
|
49 |
+
for item in item_group:
|
50 |
+
if item.get("type") == "chips":
|
51 |
+
options = item.get("options", [])
|
52 |
+
chip_opttion.extend([opt["text"] for opt in options])
|
53 |
+
all_chip_options.append(chip_opttion)
|
54 |
+
|
55 |
+
response = {"text": extracted_texts, "payload": all_chip_options}
|
56 |
+
|
57 |
+
return response
|
app/types/__pycache__/response.cpython-39.pyc
ADDED
Binary file (874 Bytes). View file
|
|
app/types/response.py
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
from typing import Optional
|
3 |
+
from pydantic import BaseModel
|
4 |
+
|
5 |
+
|
6 |
+
class Items(BaseModel):
|
7 |
+
text: list[str]
|
8 |
+
payload: list[list[str]]
|
9 |
+
|
10 |
+
class ResponseAPI(BaseModel):
|
11 |
+
status : int
|
12 |
+
data : Optional[Items] = None
|
13 |
+
|
14 |
+
class Message(BaseModel):
|
15 |
+
session_id : str
|
16 |
+
message_content: list[str]
|
main.py
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from fastapi import FastAPI
|
2 |
+
from app.api.routes import router # type: ignore
|
3 |
+
|
4 |
+
app = FastAPI(title="FastAPI Proxy Service")
|
5 |
+
|
6 |
+
app.include_router(router, prefix="/api")
|
7 |
+
|
8 |
+
if __name__ == "__main__":
|
9 |
+
import uvicorn
|
10 |
+
uvicorn.run(app, host="0.0.0.0", port=8000, reload=True)
|
requirements.txt
ADDED
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
annotated-types==0.7.0
|
2 |
+
anyio==4.8.0
|
3 |
+
cachetools==5.5.2
|
4 |
+
certifi==2025.1.31
|
5 |
+
charset-normalizer==3.4.1
|
6 |
+
click==8.1.8
|
7 |
+
colorama==0.4.6
|
8 |
+
exceptiongroup==1.2.2
|
9 |
+
fastapi==0.115.11
|
10 |
+
google-api-core==2.24.1
|
11 |
+
google-auth==2.38.0
|
12 |
+
google-cloud-dialogflow-cx==1.40.0
|
13 |
+
googleapis-common-protos==1.69.1
|
14 |
+
grpcio==1.71.0rc2
|
15 |
+
grpcio-status==1.71.0rc2
|
16 |
+
h11==0.14.0
|
17 |
+
httpcore==1.0.7
|
18 |
+
httptools==0.6.4
|
19 |
+
httpx==0.28.1
|
20 |
+
idna==3.10
|
21 |
+
Jinja2==3.1.6
|
22 |
+
MarkupSafe==3.0.2
|
23 |
+
proto-plus==1.26.0
|
24 |
+
protobuf==5.29.3
|
25 |
+
pyasn1==0.6.1
|
26 |
+
pyasn1_modules==0.4.1
|
27 |
+
pydantic==2.10.6
|
28 |
+
pydantic_core==2.27.2
|
29 |
+
python-dotenv==1.0.1
|
30 |
+
PyYAML==6.0.2
|
31 |
+
requests==2.32.3
|
32 |
+
rsa==4.9
|
33 |
+
sniffio==1.3.1
|
34 |
+
starlette==0.46.0
|
35 |
+
typing_extensions==4.12.2
|
36 |
+
urllib3==2.3.0
|
37 |
+
uvicorn==0.34.0
|
38 |
+
watchfiles==1.0.4
|
39 |
+
websockets==15.0.1
|