kltn21110's picture
Update function/gemini_response/get_table.py
6f8d9d0 verified
from langchain_community.utilities.sql_database import SQLDatabase
from langchain_experimental.sql import SQLDatabaseChain
import os, sys
import os
from dotenv import load_dotenv
# Load biến môi trường từ file .env
BASE_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), "../../")) # hoặc ".." tùy vị trí
dotenv_path = os.path.join(BASE_DIR, ".env")
import os
from dotenv import load_dotenv
# # Gán đường dẫn tuyệt đối đến file .env
# dotenv_path = r"d:\HmDrinks_Chat\V2\chatbot - 19_5\.env"
from dotenv import load_dotenv, find_dotenv
# Tự động tìm file .env gần nhất trong cây thư mục cha
load_dotenv(find_dotenv(), override=True)
# Debug kiểm tra
# print(">> DEBUG: dotenv_path =", dotenv_path)
# print(">> DEBUG: DB_HOST =", os.getenv("DB_HOST"))
# print(">> DEBUG: DB_USER =", os.getenv("DB_USER"))
# print(">> DEBUG: DB_PASSWORD =", os.getenv("DB_PASSWORD"))
# print(">> DEBUG: DB_NAME =", os.getenv("DB_NAME"))
# print(">> DEBUG: DB_PORT =", os.getenv("DB_PORT"))
DB_HOST = os.getenv("DB_HOST")
DB_USER = os.getenv("DB_USER")
DB_PASSWORD = os.getenv("DB_PASSWORD")
DB_NAME = os.getenv("DB_NAME")
DB_PORT = os.getenv("DB_PORT")
import os
from urllib.parse import quote
password = os.getenv("DB_PASSWORD")
DB_PASSWORD = quote(password)
# Tạo connection string
connection_uri = (
f"mysql+pymysql://{DB_USER}:{DB_PASSWORD}@{DB_HOST}:{DB_PORT}/{DB_NAME}"
"?ssl_verify_cert=false&ssl_verify_identity=false"
)
print(">> DEBUG connection_uri:", connection_uri)
current_dir = os.path.dirname(os.path.abspath(__file__))
project_root = os.path.abspath(os.path.join(current_dir, '..', '..')) # Lên 2 cấp
sys.path.append(project_root)
from support import get_key
api_key = get_key.get_random_api_key()
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
os.environ["GOOGLE_API_KEY"] = "AIzaSyCO-RlqYewC4e9BEPoC8m-AxHUY7J3_o2E"
import prompt.prompt_main as prompt
from langchain_google_genai import GoogleGenerativeAIEmbeddings, ChatGoogleGenerativeAI
llm1 = ChatGoogleGenerativeAI(model='gemini-2.0-flash-thinking-exp-01-21',temperature=0.6,api_key=api_key)
db = SQLDatabase.from_uri(connection_uri)
db.get_table_info_no_throw()
import re
db_chain = SQLDatabaseChain.from_llm(llm=llm1,db=db,prompt= prompt.PROMPT)
import prompt.prompt_table as prompt_table
import prompt.prompt_create_table as prompt_create
import json
# import google.generativeai as genai
# genai.configure(api_key=api_key)
# async def response_general(input:str)->list:
# api_key = get_key.get_random_api_key()
# genai.configure(api_key=api_key)
# generation_config = {
# "temperature": 1,
# "top_p": 0.95,
# "top_k": 40,
# "max_output_tokens": 8192,
# "response_mime_type": "text/plain",
# }
# model = genai.GenerativeModel(
# model_name="gemini-2.5-flash-preview-04-17",
# generation_config=generation_config,
# )
# chat_session = model.start_chat(
# history=[
# {
# "role": "user",
# "parts": [
# f"""Hãy vui lòng đọc kỹ các bảng sau đây gồm có các thuộc tÍNH, khóa ngoại của các bảng sau khi tạo bảng trong MySQL. {prompt_create.PROMPT_TABLE}.
# Mình có định nghĩa các thuộc tính tham số, mối quan hệ các bảng sau đây: {prompt_table}. Luôn đọc kĩ càng các thông tin mô tả này. Hãy xác định kĩ càng các bước, mô tả của mình để lấy các bảng cần dùng chính xác nhất.
# Hãy cân nhắc cho câu hỏi sau đây: {input}. Phân tích câu hỏi và chọn các bảng cần thiết để có thể trả lời câu hỏi.
# Hãy phân biệt rõ giữa đơn hàng bình thường(orders) và đơn hàng nhóm(group_orders).
# ** Cách trả lời:
# - Bạn vui lòng trả lại danh sách các table liên quan. Vui lòng ghép chúng vào trong list và nối với nhau bằng , ví dụ ["cart","user"].
# - Luôn bao gồm bảng user trong mọi trường hợp câu hỏi.
# - Chỉ lấy tên các bảng mà mình đã cung cấp, không được tự ý sinh thêm bảng. Điều này là cấm.
# - Không được phép dùng bảng "Token, user_chat, notification"
# - Nếu trong list có bảng cart thì phải kèm theo cart_item
# - Nếu trong list có bảng cart_group thì phải kèm theo cart_item_group
# - Nếu trong bảng có chứa các bảng như cart_item, cart_item_group thì vui lòng kèm theo các bảng liên quan về sản phẩm như product_translation và product_variants, product
# - Nếu trong list có bảng category thì phải kèm theo category_translation, product phải kèm theo product_translation và product_variant
# - Nếu trong list có bảng group_orders thì phải kèm theo group_order_members.
# - Nếu trong list có bảng group_order_members thì phải kèm theo cart_group.
# - Nếu trong list trả về có các bảng như product, post, hay category phải kèm theo bảng translation liên kết với nó.
# - Khi trong list có liên quan product hãy luôn cung cấp product_variants để có thể cung cấp thêm giá tùy trương hợp.
# - Không yêu cầu giải thích gì thêm chỉ cần trả về list theo mình mô tả ví dụ.
# - Luôn đảm bảo Xác định chính xác bảng cần dùng cho câu hỏi, không dư thừa bảng, không bỏ sót bảng cần thiết.
# - Luôn luôn trả về đúng list []. Cấm trả sai định dạng mà mình đã cung cấp""",
# ],
# }
# ]
# )
# response = chat_session.send_message("Hãy luôn đảm bảo rằng bạn tuân thủ những gì mình đưa ra, không được phép làm khác đi.")
# data = response.text
# if data.strip(): # Kiểm tra dữ liệu không rỗng
# try:
# # Cố gắng parse JSON
# data_list = json.loads(data)
# return data_list
# except json.JSONDecodeError:
# # Nếu không phải JSON, thử tìm danh sách bảng trong chuỗi văn bản
# match = re.search(r'\[(.*?)\]', data)
# if match:
# # Lấy phần trong dấu [ ], tách thành list
# items_str = match.group(1)
# items = [item.strip().strip('"').strip("'") for item in items_str.split(',')]
# print("Danh sách bảng đã trích xuất:", items)
# return items
# else:
# print("Không tìm thấy danh sách bảng trong dữ liệu văn bản!")
# else:
# print("Dữ liệu đầu vào rỗng!")
import asyncio
import json
import re
from support import get_key
import google.generativeai as genai
async def response_general(input: str) -> list:
async def call_model_once() -> list:
# Lấy API key và cấu hình
api_key = get_key.get_random_api_key()
genai.configure(api_key=api_key)
generation_config = {
"temperature": 1,
"top_p": 0.95,
"top_k": 40,
"max_output_tokens": 8192,
"response_mime_type": "text/plain",
}
model = genai.GenerativeModel(
model_name="gemini-2.5-flash-preview-04-17",
generation_config=generation_config,
)
chat_session = model.start_chat(
history=[
{
"role": "user",
"parts": [
f"""Hãy vui lòng đọc kỹ các bảng sau đây gồm có các thuộc tÍNH, khóa ngoại của các bảng sau khi tạo bảng trong MySQL. {prompt_create.PROMPT_TABLE}.
Mình có định nghĩa các thuộc tính tham số, mối quan hệ các bảng sau đây: {prompt_table}. Luôn đọc kĩ càng các thông tin mô tả này. Hãy xác định kĩ càng các bước, mô tả của mình để lấy các bảng cần dùng chính xác nhất.
Hãy cân nhắc cho câu hỏi sau đây: {input}. Phân tích câu hỏi và chọn các bảng cần thiết để có thể trả lời câu hỏi.
Hãy phân biệt rõ giữa đơn hàng bình thường(orders) và đơn hàng nhóm(group_orders).
** Cách trả lời:
- Bạn vui lòng trả lại danh sách các table liên quan. Vui lòng ghép chúng vào trong list và nối với nhau bằng , ví dụ ["cart","user"].
- Luôn bao gồm bảng user trong mọi trường hợp câu hỏi.
- Chỉ lấy tên các bảng mà mình đã cung cấp, không được tự ý sinh thêm bảng. Điều này là cấm.
- Không được phép dùng bảng "Token, user_chat, notification"
- Nếu trong list có bảng cart thì phải kèm theo cart_item
- Nếu trong list có bảng cart_group thì phải kèm theo cart_item_group
- Nếu trong bảng có chứa các bảng như cart_item, cart_item_group thì vui lòng kèm theo các bảng liên quan về sản phẩm như product_translation và product_variants, product
- Nếu trong list có bảng category thì phải kèm theo category_translation, product phải kèm theo product_translation và product_variant
- Nếu trong list có bảng group_orders thì phải kèm theo group_order_members.
- Nếu trong list có bảng group_order_members thì phải kèm theo cart_group.
- Nếu trong list trả về có các bảng như product, post, hay category phải kèm theo bảng translation liên kết với nó.
- Khi trong list có liên quan product hãy luôn cung cấp product_variants để có thể cung cấp thêm giá tùy trương hợp.
- Không yêu cầu giải thích gì thêm chỉ cần trả về list theo mình mô tả ví dụ.
- Luôn đảm bảo Xác định chính xác bảng cần dùng cho câu hỏi, không dư thừa bảng, không bỏ sót bảng cần thiết.
- Luôn luôn trả về đúng list []. Cấm trả sai định dạng mà mình đã cung cấp""",
],
}
]
)
response = await chat_session.send_message_async("Hãy luôn đảm bảo rằng bạn tuân thủ những gì mình đưa ra, không được phép làm khác đi.")
data = response.text
if data.strip():
try:
return json.loads(data)
except json.JSONDecodeError:
match = re.search(r'\[(.*?)\]', data)
if match:
items_str = match.group(1)
items = [item.strip().strip('"').strip("'") for item in items_str.split(',')]
print("✅ Danh sách bảng đã trích xuất:", items)
return items
else:
raise ValueError("Không tìm thấy danh sách bảng hợp lệ trong phản hồi văn bản.")
else:
raise ValueError("Dữ liệu phản hồi trống.")
# Gọi lần đầu
try:
return await call_model_once()
except Exception as e:
print(f"⚠️ Lỗi lần đầu: {e} — thử lại sau 2 giây...")
await asyncio.sleep(2)
try:
return await call_model_once()
except Exception as retry_error:
print(f"❌ Lỗi lần 2: {retry_error}")
raise Exception("Gọi mô hình thất bại sau khi thử lại.")
# if __name__ == "__main__":
# import asyncio
# asyncio.run(response_general("Danh sách bài đăng mới nhất"))