import json from collections import defaultdict # Configure OpenAI KEY import os from dotenv import load_dotenv from openai import OpenAI # Load environment variables from .env file load_dotenv() api_key = os.getenv("OPENAI_API_KEY") # 'ollama' model = "gpt-4o-mini" # "gpt-4o-mini" base_url = None products_file = 'products.json' categories_file = 'categories.json' delimiter = "####" step_2_system_message_content = f""" You will be provided with customer service a conversation. \ The most recent user query will be delimited with \ {delimiter} characters. Output a python list of objects, where each object has \ the following format: 'category': , OR 'products': Where the categories and products must be found in \ the customer service query. If a product is mentioned, it must be associated with \ the correct category in the allowed products list below. If no products or categories are found, output an \ empty list. Only list products and categories that have not already \ been mentioned and discussed in the earlier parts of \ the conversation. Allowed products: Computers and Laptops category: TechPro Ultrabook BlueWave Gaming Laptop PowerLite Convertible TechPro Desktop BlueWave Chromebook Smartphones and Accessories category: SmartX ProPhone MobiTech PowerCase SmartX MiniPhone MobiTech Wireless Charger SmartX EarBuds Televisions and Home Theater Systems category: CineView 4K TV SoundMax Home Theater CineView 8K TV SoundMax Soundbar CineView OLED TV Gaming Consoles and Accessories category: GameSphere X ProGamer Controller GameSphere Y ProGamer Racing Wheel GameSphere VR Headset Audio Equipment category: AudioPhonic Noise-Canceling Headphones WaveSound Bluetooth Speaker AudioPhonic True Wireless Earbuds WaveSound Soundbar AudioPhonic Turntable Cameras and Camcorders category: FotoSnap DSLR Camera ActionCam 4K FotoSnap Mirrorless Camera ZoomMaster Camcorder FotoSnap Instant Camera Only output the list of objects, with nothing else. """ step_2_system_message = {'role':'system', 'content': step_2_system_message_content} # sys message for response to user step_4_system_message_content = f""" You are a customer service assistant for a large electronic store. \ Respond in a friendly and helpful tone, with VERY concise answers. \ Make sure to ask the user relevant follow-up questions. """ step_4_system_message = {'role':'system', 'content': step_4_system_message_content} # sys message for evaluation step_6_system_message_content = f""" You are an assistant that evaluates whether \ customer service agent responses sufficiently \ answer customer questions, and also validates that \ all the facts the assistant cites from the product \ information are correct. The conversation history, product information, user and customer \ service agent messages will be delimited by \ 3 backticks, i.e. ```. Respond with a Y or N character, with no punctuation: Y - if the output sufficiently answers the question \ AND the response correctly uses product information N - otherwise Output a single letter only. """ step_6_system_message = {'role':'system', 'content': step_6_system_message_content} # Set your OpenAI API key from the environment variable #api_key = os.getenv("HYPERBOLIC_API_KEY") # 'ollama' #model = "meta-llama/Llama-3.2-90B-Vision-Instruct" # "gpt-4o-mini" #base_url = "https://api.hyperbolic.xyz/v1/" # ollama 'http://localhost:11434/v1/' client = OpenAI( base_url=base_url, api_key=api_key ) def get_completion_from_messages(messages, model="gpt-4o-mini", temperature=0, max_tokens=500): ''' Encapsulate a function to access LLM Parameters: messages: This is a list of messages, each message is a dictionary containing role and content. The role can be 'system', 'user' or 'assistant', and the content is the message of the role. model: The model to be called, default is gpt-4o-mini (ChatGPT) temperature: This determines the randomness of the model output, default is 0, meaning the output will be very deterministic. Increasing temperature will make the output more random. max_tokens: This determines the maximum number of tokens in the model output. ''' response = client.chat.completions.create( messages=messages, model = model, temperature=temperature, # This determines the randomness of the model's output max_tokens=max_tokens, # This determines the maximum number of tokens in the model's output ) return response.choices[0].message.content def create_categories(): categories_dict = { 'Billing': [ 'Unsubscribe or upgrade', 'Add a payment method', 'Explanation for charge', 'Dispute a charge'], 'Technical Support':[ 'General troubleshooting' 'Device compatibility', 'Software updates'], 'Account Management':[ 'Password reset' 'Update personal information', 'Close account', 'Account security'], 'General Inquiry':[ 'Product information' 'Pricing', 'Feedback', 'Speak to a human'] } with open(categories_file, 'w') as file: json.dump(categories_dict, file) return categories_dict def get_categories(): with open(categories_file, 'r') as file: categories = json.load(file) return categories def get_product_list(): """ 具体原理参见第四节课 """ products = get_products() product_list = [] for product in products.keys(): product_list.append(product) return product_list def get_products_and_category(): """ 具体原理参见第五节课 """ products = get_products() products_by_category = defaultdict(list) for product_name, product_info in products.items(): category = product_info.get('category') if category: products_by_category[category].append(product_info.get('name')) return dict(products_by_category) def get_products(): with open(products_file, 'r') as file: products = json.load(file) return products # Get cate and products from user def find_category_and_product(user_input,products_and_category): delimiter = "####" system_message = f""" You will be provided with customer service queries. \ The customer service query will be delimited with {delimiter} characters. Output a python list of json objects, where each object has the following format: 'category': , OR 'products': Where the categories and products must be found in the customer service query. If a product is mentioned, it must be associated with the correct category in the allowed products list below. If no products or categories are found, output an empty list. The allowed products are provided in JSON format. The keys of each item represent the category. The values of each item is a list of products that are within that category. Allowed products: {products_and_category} """ messages = [ {'role':'system', 'content': system_message}, {'role':'user', 'content': f"{delimiter}{user_input}{delimiter}"}, ] return get_completion_from_messages(messages) # Add allowed products def find_category_and_product_only(user_input,products_and_category): delimiter = "####" system_message = f""" You will be provided with customer service queries. \ The customer service query will be delimited with {delimiter} characters. Output a python list of objects, where each object has the following format: 'category': , OR 'products': Where the categories and products must be found in the customer service query. If a product is mentioned, it must be associated with the correct category in the allowed products list below. If no products or categories are found, output an empty list. Allowed products: Computers and Laptops category: TechPro Ultrabook BlueWave Gaming Laptop PowerLite Convertible TechPro Desktop BlueWave Chromebook Smartphones and Accessories category: SmartX ProPhone MobiTech PowerCase SmartX MiniPhone MobiTech Wireless Charger SmartX EarBuds Televisions and Home Theater Systems category: CineView 4K TV SoundMax Home Theater CineView 8K TV SoundMax Soundbar CineView OLED TV Gaming Consoles and Accessories category: GameSphere X ProGamer Controller GameSphere Y ProGamer Racing Wheel GameSphere VR Headset Audio Equipment category: AudioPhonic Noise-Canceling Headphones WaveSound Bluetooth Speaker AudioPhonic True Wireless Earbuds WaveSound Soundbar AudioPhonic Turntable Cameras and Camcorders category: FotoSnap DSLR Camera ActionCam 4K FotoSnap Mirrorless Camera ZoomMaster Camcorder FotoSnap Instant Camera Only output the list of objects, nothing else. """ messages = [ {'role':'system', 'content': system_message}, {'role':'user', 'content': f"{delimiter}{user_input}{delimiter}"}, ] return get_completion_from_messages(messages) # Get product from user query def get_products_from_query(user_msg): products_and_category = get_products_and_category() delimiter = "####" system_message = f""" You will be provided with customer service queries. \ The customer service query will be delimited with {delimiter} characters. Output a python list of json objects, where each object has the following format: 'category': , OR 'products': Where the categories and products must be found in the customer service query. If a product is mentioned, it must be associated with the correct category in the allowed products list below. If no products or categories are found, output an empty list. The allowed products are provided in JSON format. The keys of each item represent the category. The values of each item is a list of products that are within that category. Allowed products: {products_and_category} """ messages = [ {'role':'system', 'content': system_message}, {'role':'user', 'content': f"{delimiter}{user_msg}{delimiter}"}, ] category_and_product_response = get_completion_from_messages(messages) return category_and_product_response def get_product_by_name(name): products = get_products() return products.get(name, None) def get_products_by_category(category): products = get_products() return [product for product in products.values() if product["category"] == category] def get_mentioned_product_info(data_list): """ 具体原理参见第五、六节课 """ product_info_l = [] if data_list is None: return product_info_l for data in data_list: try: if "products" in data: products_list = data["products"] for product_name in products_list: product = get_product_by_name(product_name) if product: product_info_l.append(product) else: print(f"Error: Product '{product_name}' not found") elif "category" in data: category_name = data["category"] category_products = get_products_by_category(category_name) for product in category_products: product_info_l.append(product) else: print("Error: Invalid object format") except Exception as e: print(f"Error: {e}") return product_info_l def read_string_to_list(input_string): if input_string is None: return None try: input_string = input_string.replace("'", "\"") # Replace single quotes with double quotes for valid JSON data = json.loads(input_string) return data except json.JSONDecodeError: print("Error: Invalid JSON string") return None def generate_output_string(data_list): output_string = "" if data_list is None: return output_string for data in data_list: try: if "products" in data: products_list = data["products"] for product_name in products_list: product = get_product_by_name(product_name) if product: output_string += json.dumps(product, indent=4) + "\n" else: print(f"Error: Product '{product_name}' not found") elif "category" in data: category_name = data["category"] category_products = get_products_by_category(category_name) for product in category_products: output_string += json.dumps(product, indent=4) + "\n" else: print("Error: Invalid object format") except Exception as e: print(f"Error: {e}") return output_string # Example usage: #product_information_for_user_message_1 = generate_output_string(category_and_product_list) #print(product_information_for_user_message_1) # Answer questions from customers def answer_user_msg(user_msg,product_info): """ 代码参见第五节课 """ delimiter = "####" system_message = f""" You are a customer service assistant for a large electronic store. \ Respond in a friendly and helpful tone, with concise answers. \ Make sure to ask the user relevant follow up questions. """ # user_msg = f""" # tell me about the smartx pro phone and the fotosnap camera, the dslr one. Also what tell me about your tvs""" messages = [ {'role':'system', 'content': system_message}, {'role':'user', 'content': f"{delimiter}{user_msg}{delimiter}"}, {'role':'assistant', 'content': f"Relevant product information:\n{product_info}"}, ] response = get_completion_from_messages(messages) return response # 创建并存入商品数据 def create_products(): """ Create products dictionary and save it to a file named products.json """ # product information # fun fact: all these products are fake and were generated by a language model products = { "TechPro Ultrabook": { "name": "TechPro Ultrabook", "category": "Computers and Laptops", "brand": "TechPro", "model_number": "TP-UB100", "warranty": "1 year", "rating": 4.5, "features": ["13.3-inch display", "8GB RAM", "256GB SSD", "Intel Core i5 processor"], "description": "A sleek and lightweight ultrabook for everyday use.", "price": 799.99 }, "BlueWave Gaming Laptop": { "name": "BlueWave Gaming Laptop", "category": "Computers and Laptops", "brand": "BlueWave", "model_number": "BW-GL200", "warranty": "2 years", "rating": 4.7, "features": ["15.6-inch display", "16GB RAM", "512GB SSD", "NVIDIA GeForce RTX 3060"], "description": "A high-performance gaming laptop for an immersive experience.", "price": 1199.99 }, "PowerLite Convertible": { "name": "PowerLite Convertible", "category": "Computers and Laptops", "brand": "PowerLite", "model_number": "PL-CV300", "warranty": "1 year", "rating": 4.3, "features": ["14-inch touchscreen", "8GB RAM", "256GB SSD", "360-degree hinge"], "description": "A versatile convertible laptop with a responsive touchscreen.", "price": 699.99 }, "TechPro Desktop": { "name": "TechPro Desktop", "category": "Computers and Laptops", "brand": "TechPro", "model_number": "TP-DT500", "warranty": "1 year", "rating": 4.4, "features": ["Intel Core i7 processor", "16GB RAM", "1TB HDD", "NVIDIA GeForce GTX 1660"], "description": "A powerful desktop computer for work and play.", "price": 999.99 }, "BlueWave Chromebook": { "name": "BlueWave Chromebook", "category": "Computers and Laptops", "brand": "BlueWave", "model_number": "BW-CB100", "warranty": "1 year", "rating": 4.1, "features": ["11.6-inch display", "4GB RAM", "32GB eMMC", "Chrome OS"], "description": "A compact and affordable Chromebook for everyday tasks.", "price": 249.99 }, "SmartX ProPhone": { "name": "SmartX ProPhone", "category": "Smartphones and Accessories", "brand": "SmartX", "model_number": "SX-PP10", "warranty": "1 year", "rating": 4.6, "features": ["6.1-inch display", "128GB storage", "12MP dual camera", "5G"], "description": "A powerful smartphone with advanced camera features.", "price": 899.99 }, "MobiTech PowerCase": { "name": "MobiTech PowerCase", "category": "Smartphones and Accessories", "brand": "MobiTech", "model_number": "MT-PC20", "warranty": "1 year", "rating": 4.3, "features": ["5000mAh battery", "Wireless charging", "Compatible with SmartX ProPhone"], "description": "A protective case with built-in battery for extended usage.", "price": 59.99 }, "SmartX MiniPhone": { "name": "SmartX MiniPhone", "category": "Smartphones and Accessories", "brand": "SmartX", "model_number": "SX-MP5", "warranty": "1 year", "rating": 4.2, "features": ["4.7-inch display", "64GB storage", "8MP camera", "4G"], "description": "A compact and affordable smartphone for basic tasks.", "price": 399.99 }, "MobiTech Wireless Charger": { "name": "MobiTech Wireless Charger", "category": "Smartphones and Accessories", "brand": "MobiTech", "model_number": "MT-WC10", "warranty": "1 year", "rating": 4.5, "features": ["10W fast charging", "Qi-compatible", "LED indicator", "Compact design"], "description": "A convenient wireless charger for a clutter-free workspace.", "price": 29.99 }, "SmartX EarBuds": { "name": "SmartX EarBuds", "category": "Smartphones and Accessories", "brand": "SmartX", "model_number": "SX-EB20", "warranty": "1 year", "rating": 4.4, "features": ["True wireless", "Bluetooth 5.0", "Touch controls", "24-hour battery life"], "description": "Experience true wireless freedom with these comfortable earbuds.", "price": 99.99 }, "CineView 4K TV": { "name": "CineView 4K TV", "category": "Televisions and Home Theater Systems", "brand": "CineView", "model_number": "CV-4K55", "warranty": "2 years", "rating": 4.8, "features": ["55-inch display", "4K resolution", "HDR", "Smart TV"], "description": "A stunning 4K TV with vibrant colors and smart features.", "price": 599.99 }, "SoundMax Home Theater": { "name": "SoundMax Home Theater", "category": "Televisions and Home Theater Systems", "brand": "SoundMax", "model_number": "SM-HT100", "warranty": "1 year", "rating": 4.4, "features": ["5.1 channel", "1000W output", "Wireless subwoofer", "Bluetooth"], "description": "A powerful home theater system for an immersive audio experience.", "price": 399.99 }, "CineView 8K TV": { "name": "CineView 8K TV", "category": "Televisions and Home Theater Systems", "brand": "CineView", "model_number": "CV-8K65", "warranty": "2 years", "rating": 4.9, "features": ["65-inch display", "8K resolution", "HDR", "Smart TV"], "description": "Experience the future of television with this stunning 8K TV.", "price": 2999.99 }, "SoundMax Soundbar": { "name": "SoundMax Soundbar", "category": "Televisions and Home Theater Systems", "brand": "SoundMax", "model_number": "SM-SB50", "warranty": "1 year", "rating": 4.3, "features": ["2.1 channel", "300W output", "Wireless subwoofer", "Bluetooth"], "description": "Upgrade your TV's audio with this sleek and powerful soundbar.", "price": 199.99 }, "CineView OLED TV": { "name": "CineView OLED TV", "category": "Televisions and Home Theater Systems", "brand": "CineView", "model_number": "CV-OLED55", "warranty": "2 years", "rating": 4.7, "features": ["55-inch display", "4K resolution", "HDR", "Smart TV"], "description": "Experience true blacks and vibrant colors with this OLED TV.", "price": 1499.99 }, "GameSphere X": { "name": "GameSphere X", "category": "Gaming Consoles and Accessories", "brand": "GameSphere", "model_number": "GS-X", "warranty": "1 year", "rating": 4.9, "features": ["4K gaming", "1TB storage", "Backward compatibility", "Online multiplayer"], "description": "A next-generation gaming console for the ultimate gaming experience.", "price": 499.99 }, "ProGamer Controller": { "name": "ProGamer Controller", "category": "Gaming Consoles and Accessories", "brand": "ProGamer", "model_number": "PG-C100", "warranty": "1 year", "rating": 4.2, "features": ["Ergonomic design", "Customizable buttons", "Wireless", "Rechargeable battery"], "description": "A high-quality gaming controller for precision and comfort.", "price": 59.99 }, "GameSphere Y": { "name": "GameSphere Y", "category": "Gaming Consoles and Accessories", "brand": "GameSphere", "model_number": "GS-Y", "warranty": "1 year", "rating": 4.8, "features": ["4K gaming", "500GB storage", "Backward compatibility", "Online multiplayer"], "description": "A compact gaming console with powerful performance.", "price": 399.99 }, "ProGamer Racing Wheel": { "name": "ProGamer Racing Wheel", "category": "Gaming Consoles and Accessories", "brand": "ProGamer", "model_number": "PG-RW200", "warranty": "1 year", "rating": 4.5, "features": ["Force feedback", "Adjustable pedals", "Paddle shifters", "Compatible with GameSphere X"], "description": "Enhance your racing games with this realistic racing wheel.", "price": 249.99 }, "GameSphere VR Headset": { "name": "GameSphere VR Headset", "category": "Gaming Consoles and Accessories", "brand": "GameSphere", "model_number": "GS-VR", "warranty": "1 year", "rating": 4.6, "features": ["Immersive VR experience", "Built-in headphones", "Adjustable headband", "Compatible with GameSphere X"], "description": "Step into the world of virtual reality with this comfortable VR headset.", "price": 299.99 }, "AudioPhonic Noise-Canceling Headphones": { "name": "AudioPhonic Noise-Canceling Headphones", "category": "Audio Equipment", "brand": "AudioPhonic", "model_number": "AP-NC100", "warranty": "1 year", "rating": 4.6, "features": ["Active noise-canceling", "Bluetooth", "20-hour battery life", "Comfortable fit"], "description": "Experience immersive sound with these noise-canceling headphones.", "price": 199.99 }, "WaveSound Bluetooth Speaker": { "name": "WaveSound Bluetooth Speaker", "category": "Audio Equipment", "brand": "WaveSound", "model_number": "WS-BS50", "warranty": "1 year", "rating": 4.5, "features": ["Portable", "10-hour battery life", "Water-resistant", "Built-in microphone"], "description": "A compact and versatile Bluetooth speaker for music on the go.", "price": 49.99 }, "AudioPhonic True Wireless Earbuds": { "name": "AudioPhonic True Wireless Earbuds", "category": "Audio Equipment", "brand": "AudioPhonic", "model_number": "AP-TW20", "warranty": "1 year", "rating": 4.4, "features": ["True wireless", "Bluetooth 5.0", "Touch controls", "18-hour battery life"], "description": "Enjoy music without wires with these comfortable true wireless earbuds.", "price": 79.99 }, "WaveSound Soundbar": { "name": "WaveSound Soundbar", "category": "Audio Equipment", "brand": "WaveSound", "model_number": "WS-SB40", "warranty": "1 year", "rating": 4.3, "features": ["2.0 channel", "80W output", "Bluetooth", "Wall-mountable"], "description": "Upgrade your TV's audio with this slim and powerful soundbar.", "price": 99.99 }, "AudioPhonic Turntable": { "name": "AudioPhonic Turntable", "category": "Audio Equipment", "brand": "AudioPhonic", "model_number": "AP-TT10", "warranty": "1 year", "rating": 4.2, "features": ["3-speed", "Built-in speakers", "Bluetooth", "USB recording"], "description": "Rediscover your vinyl collection with this modern turntable.", "price": 149.99 }, "FotoSnap DSLR Camera": { "name": "FotoSnap DSLR Camera", "category": "Cameras and Camcorders", "brand": "FotoSnap", "model_number": "FS-DSLR200", "warranty": "1 year", "rating": 4.7, "features": ["24.2MP sensor", "1080p video", "3-inch LCD", "Interchangeable lenses"], "description": "Capture stunning photos and videos with this versatile DSLR camera.", "price": 599.99 }, "ActionCam 4K": { "name": "ActionCam 4K", "category": "Cameras and Camcorders", "brand": "ActionCam", "model_number": "AC-4K", "warranty": "1 year", "rating": 4.4, "features": ["4K video", "Waterproof", "Image stabilization", "Wi-Fi"], "description": "Record your adventures with this rugged and compact 4K action camera.", "price": 299.99 }, "FotoSnap Mirrorless Camera": { "name": "FotoSnap Mirrorless Camera", "category": "Cameras and Camcorders", "brand": "FotoSnap", "model_number": "FS-ML100", "warranty": "1 year", "rating": 4.6, "features": ["20.1MP sensor", "4K video", "3-inch touchscreen", "Interchangeable lenses"], "description": "A compact and lightweight mirrorless camera with advanced features.", "price": 799.99 }, "ZoomMaster Camcorder": { "name": "ZoomMaster Camcorder", "category": "Cameras and Camcorders", "brand": "ZoomMaster", "model_number": "ZM-CM50", "warranty": "1 year", "rating": 4.3, "features": ["1080p video", "30x optical zoom", "3-inch LCD", "Image stabilization"], "description": "Capture life's moments with this easy-to-use camcorder.", "price": 249.99 }, "FotoSnap Instant Camera": { "name": "FotoSnap Instant Camera", "category": "Cameras and Camcorders", "brand": "FotoSnap", "model_number": "FS-IC10", "warranty": "1 year", "rating": 4.1, "features": ["Instant prints", "Built-in flash", "Selfie mirror", "Battery-powered"], "description": "Create instant memories with this fun and portable instant camera.", "price": 69.99 } } products_file = 'products.json' with open(products_file, 'w') as file: json.dump(products, file) return products