from langchain_core.tools import tool from langchain_openai import ChatOpenAI import os import os,sys BASE_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), "../../")) sys.path.insert(0, BASE_DIR) import function.gemini_response.filter_query_internal as filter_query #Test OpenAI os.environ["OPENAI_API_KEY"] = "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" llm = ChatOpenAI(model="gpt-4.1") #Test google os.environ["GOOGLE_API_KEY"] = "AIzaSyB_7ahCuAOZU0UKcON_A00ya5breHTEgQM" from langchain_google_genai import GoogleGenerativeAIEmbeddings, ChatGoogleGenerativeAI llm1 = ChatGoogleGenerativeAI(model='gemini-2.5-flash-preview-05-20',temperature=0.6) from langchain_core.messages import HumanMessage, ToolMessage @tool def question_information(query: str) -> str: """ Trả lời các câu hỏi về thông tin liên hệ của cửa hàng, thông tin về sinh viên, tên đề tài các nội dung liên quan mà không phải sql Hàm này chỉ phục vụ mục đích cung cấp thông tin liên lạc của cửa hàng, bao gồm: - Số điện thoại liên hệ. - Địa chỉ cửa hàng. - Giờ làm việc. - Email hỗ trợ. - Các kênh liên hệ khác như Facebook, Zalo, v.v. ⚠️ Lưu ý: - Hàm này KHÔNG trả lời các câu hỏi khác như: gợi ý món ăn, tư vấn sản phẩm, giá cả, chương trình khuyến mãi, cách pha chế đồ uống, v.v. - Nếu truy vấn không liên quan đến thông tin cửa hàng, hàm sẽ từ chối trả lời. Args: query (str): Câu hỏi của người dùng liên quan đến thông tin liên hệ của cửa hàng. bao gồm: - Số điện thoại liên hệ. - Địa chỉ cửa hàng. - Giờ làm việc. - Email hỗ trợ. - Các kênh liên hệ khác như Facebook, Zalo, v.v. Returns: str: Thông tin liên hệ của cửa hàng hoặc thông báo từ chối nếu câu hỏi không phù hợp. Xác định rõ câu hỏi không viết gọn """ return query @tool(description="Vui lòng giữ đúng truy vấn người dùng không tạo ra câu truy vấn khác ý nghĩa câu hỏi người dùng định hỏi, (**yêu cầu phải bám sát không được tự sinh câu hỏi)") def question_sql(query: str)->str: """ Hỗ trợ truy xuất schema của database để giúp tạo truy vấn SQL cho các bảng sau: - **Giỏ hàng (cart, cart_item)** - **Danh mục sản phẩm(tên sản phẩm) (category, category_translation)** - **Liên hệ và yêu thích (contact, favourite, favourite_item)** - **Thông báo (notification)** - **Đơn hàng (orders, order_item, shipment)** - **Thanh toán (otp, payments)** - **Bài viết & tin tức (post, post_translation)** - **Lịch sử giá (price_history)** - **Sản phẩm (product, product_translation, product_variants)** - **Đánh giá sản phẩm (review)** - **Người dùng (user, user_coin, token)** - **Mã giảm giá & phiếu giảm giá (voucher, user_voucher)** - **Xác nhận về mua/xem, xóa giỏ hàng, đơn hàng**(Hãy lưu ý những câu hỏi về này) ⚠ **Lưu ý**: - Chỉ hỗ trợ truy vấn liên quan đến các bảng trong database. - Không trả lời các câu hỏi về thông tin cửa hàng như số điện thoại, email, giờ làm việc. Args: query (str): Câu hỏi liên quan đến việc truy vấn dữ liệu từ database. Returns: str: Mô tả bảng tương ứng hoặc thông báo từ chối nếu câu hỏi không phù hợp. """ return query @tool def question_general(query: str) -> str: """ Xử lý các câu hỏi không liên quan đến các công cụ có sẵn. Hàm này nhận vào một câu hỏi dưới dạng chuỗi và trả về câu hỏi đó mà không thực hiện bất kỳ xử lý nào khác. Nó có thể được sử dụng như một phương án dự phòng khi không có tool nào phù hợp để xử lý câu hỏi. Args: query (str): Câu hỏi đầu vào từ người dùng. Returns: str: Trả về chính câu hỏi mà không thay đổi. """ return query @tool(description="""ác định xem truy vấn có phải là câu chào hỏi hay không. Câu chào hỏi bao gồm các từ hoặc cụm từ thể hiện sự chào đón, bắt đầu cuộc trò chuyện, chẳng hạn như: - "Xin chào", "Chào bạn", "Hello", "Hi", "Hey", "Good morning", "Good evening", ... - Cụm từ mang ý nghĩa xã giao: "Rất vui được gặp bạn", "Hôm nay bạn thế nào?", "Chúc một ngày tốt lành", ... Lưu ý: - Chỉ xử lý các câu hỏi thuộc nhóm chào hỏi. - Không liên quan đến **question_sql** hoặc các câu hỏi về dữ liệu. Args: query (str): Câu hỏi đầu vào của người dùng. Returns: str: Trả về câu hỏi nếu nó thuộc nhóm chào hỏi, ngược lại có thể xử lý theo yêu cầu cụ thể.""") def question_hello(query: str)->str: """ Xác định xem truy vấn có phải là câu chào hỏi hay không. Câu chào hỏi bao gồm các từ hoặc cụm từ thể hiện sự chào đón, bắt đầu cuộc trò chuyện, chẳng hạn như: - "Xin chào", "Chào bạn", "Hello", "Hi", "Hey", "Good morning", "Good evening", ... - Cụm từ mang ý nghĩa xã giao: "Rất vui được gặp bạn", "Hôm nay bạn thế nào?", "Chúc một ngày tốt lành", ... Lưu ý: - Chỉ xử lý các câu hỏi thuộc nhóm chào hỏi. - Không liên quan đến **question_sql** hoặc các câu hỏi về dữ liệu. Args: query (str): Câu hỏi đầu vào của người dùng. Returns: str: Trả về câu hỏi nếu nó thuộc nhóm chào hỏi, ngược lại có thể xử lý theo yêu cầu cụ thể. """ return query import asyncio import importlib import function.chat as chat_module async def update_tool_calls(tool_calls, chat_id,user_id,user_input): updated_calls = [] for tool in tool_calls: query = tool['args']['query'] list_history = await chat_module.get_chat_details_text(chat_id, user_id) new_question = await filter_query.response_rename_question(user_input, list_history, query) tool['args']['query'] = new_question new_name = await filter_query.response_general(new_question, list_history) if new_name is not None and new_name == "question_sql": tool['name'] = new_name.strip() updated_calls.append(tool) if new_name == "question_general": tool['name'] = new_name.strip() updated_calls.append(tool) return updated_calls else: return tool_calls return updated_calls async def process_user_query(user_input, user_id, role, language,chat_id): always_call_tool_llm = llm.bind_tools([question_information, question_sql, question_hello], tool_choice=True,strict=True) tool_calls = always_call_tool_llm.invoke(f"{user_input}").tool_calls for tc in tool_calls: tc["user_id"] = user_id tc["role"] = role tc["language"] = language print("Tool gốc:",tool_calls) data = await update_tool_calls(tool_calls,chat_id,user_id,user_input) for item in data: item['chat_id'] = chat_id print("Tool update: ", data) return data # import asyncio async def main(): await process_user_query("Tôi muốn thêm trà chanh size L vào giỏ hàng", 4, "CUSTOMER", "VN", "67d2fc6607b51a01e3beb501") if __name__ == "__main__": loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) loop.run_until_complete(main()) loop.close()