OnlyBiggg commited on
Commit
d73e455
·
1 Parent(s): e7ac3a5

first commit

Browse files
.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