CD17 commited on
Commit
6d4e4df
·
verified ·
1 Parent(s): 74ae61b

Updata app.py

Browse files
Files changed (1) hide show
  1. app.py +213 -60
app.py CHANGED
@@ -1,64 +1,217 @@
 
 
 
 
 
1
  import gradio as gr
2
- from huggingface_hub import InferenceClient
3
-
4
- """
5
- For more information on `huggingface_hub` Inference API support, please check the docs: https://huggingface.co/docs/huggingface_hub/v0.22.2/en/guides/inference
6
- """
7
- client = InferenceClient("HuggingFaceH4/zephyr-7b-beta")
8
-
9
-
10
- def respond(
11
- message,
12
- history: list[tuple[str, str]],
13
- system_message,
14
- max_tokens,
15
- temperature,
16
- top_p,
17
- ):
18
- messages = [{"role": "system", "content": system_message}]
19
-
20
- for val in history:
21
- if val[0]:
22
- messages.append({"role": "user", "content": val[0]})
23
- if val[1]:
24
- messages.append({"role": "assistant", "content": val[1]})
25
-
26
- messages.append({"role": "user", "content": message})
27
-
28
- response = ""
29
-
30
- for message in client.chat_completion(
31
- messages,
32
- max_tokens=max_tokens,
33
- stream=True,
34
- temperature=temperature,
35
- top_p=top_p,
36
- ):
37
- token = message.choices[0].delta.content
38
-
39
- response += token
40
- yield response
41
-
42
-
43
- """
44
- For information on how to customize the ChatInterface, peruse the gradio docs: https://www.gradio.app/docs/chatinterface
45
- """
46
- demo = gr.ChatInterface(
47
- respond,
48
- additional_inputs=[
49
- gr.Textbox(value="You are a friendly Chatbot.", label="System message"),
50
- gr.Slider(minimum=1, maximum=2048, value=512, step=1, label="Max new tokens"),
51
- gr.Slider(minimum=0.1, maximum=4.0, value=0.7, step=0.1, label="Temperature"),
52
- gr.Slider(
53
- minimum=0.1,
54
- maximum=1.0,
55
- value=0.95,
56
- step=0.05,
57
- label="Top-p (nucleus sampling)",
58
- ),
59
- ],
60
  )
61
 
62
 
63
- if __name__ == "__main__":
64
- demo.launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Configure OpenAI KEY
2
+ import openai as OpenAI
3
+ from dotenv import load_dotenv
4
+ from openai import OpenAI
5
+ import os
6
  import gradio as gr
7
+
8
+ # Utility package for English Prompts
9
+ import utils
10
+ import json
11
+ from datetime import datetime
12
+
13
+
14
+ # Load environment variables from .env file
15
+ load_dotenv()
16
+
17
+ # Set your OpenAI API key from the environment variable
18
+ #api_key = os.getenv("HYPERBOLIC_API_KEY") # 'ollama'
19
+ #model = "meta-llama/Llama-3.2-90B-Vision-Instruct" # "gpt-4o-mini"
20
+ #base_url = "https://api.hyperbolic.xyz/v1/" # ollama 'http://localhost:11434/v1/'
21
+
22
+ api_key = os.getenv("OPENAI_API_KEY") # 'ollama'
23
+ model = "gpt-4o-mini" # "gpt-4o-mini"
24
+ base_url = None
25
+
26
+
27
+ client = OpenAI(
28
+ base_url=base_url,
29
+ api_key=api_key
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  )
31
 
32
 
33
+ def get_completion_from_messages(messages,
34
+ model="gpt-4o-mini",
35
+ temperature=0,
36
+ max_tokens=500):
37
+ '''
38
+ Encapsulate a function to access LLM
39
+
40
+ Parameters:
41
+ 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.
42
+ model: The model to be called, default is gpt-4o-mini (ChatGPT)
43
+ 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.
44
+ max_tokens: This determines the maximum number of tokens in the model output.
45
+ '''
46
+ response = client.chat.completions.create(
47
+ messages=messages,
48
+ model=model,
49
+ temperature=temperature, # This determines the randomness of the model's output
50
+ max_tokens=max_tokens, # This determines the maximum number of tokens in the model's output
51
+ )
52
+
53
+ return response.choices[0].message.content
54
+
55
+ def process_user_message(user_input, all_messages, debug=True):
56
+ """
57
+ Preprocess user messages
58
+
59
+ Parameters:
60
+ user_input : User input
61
+ all_messages : Historical messages
62
+ debug : Whether to enable DEBUG mode, enabled by default
63
+ """
64
+ # Delimiter
65
+ delimiter = "```"
66
+
67
+ # Step 1: Use OpenAI's Moderation API to check if the user input is compliant or an injected Prompt
68
+ response = client.moderations.create(input=user_input)
69
+ moderation_output = response.results[0]
70
+
71
+ # The input is non-compliant after Moderation API check
72
+ if moderation_output.flagged:
73
+ print("Step 1: Input rejected by Moderation")
74
+ return "Sorry, your request is non-compliant"
75
+
76
+ # If DEBUG mode is enabled, print real-time progress
77
+ if debug:
78
+ print("Step 1: Input passed Moderation check")
79
+ print(f"\n**user_input**: {user_input}\n\n")
80
+
81
+ # Step 2: Extract products and corresponding categories
82
+ category_and_product_response = utils.find_category_and_product_only(
83
+ user_input, utils.get_products_and_category())
84
+ #print(category_and_product_response)
85
+ # Convert the extracted string to a list
86
+ category_and_product_list = utils.read_string_to_list(category_and_product_response)
87
+ #print(category_and_product_list)
88
+
89
+ if debug: print("Step 2: Extracted product list")
90
+
91
+ # Step 3: Find corresponding product information
92
+ product_information = utils.generate_output_string(category_and_product_list)
93
+ if debug:
94
+ print("Step 3: Found information for extracted products")
95
+ print(f"\n**product_information**: {product_information}\n\n")
96
+
97
+ # Step 4: Generate answer based on information
98
+ system_message = f"""
99
+ You are a customer service assistant for a large electronic store. \
100
+ Respond in a friendly and helpful tone, with concise answers. \
101
+ Make sure to ask the user relevant follow-up questions.
102
+ """
103
+ # Insert message
104
+ messages = [
105
+ {'role': 'system', 'content': system_message},
106
+ {'role': 'user', 'content': f"{delimiter}{user_input}{delimiter}"},
107
+ {'role': 'assistant', 'content': f"Relevant product information:\n{product_information}"}
108
+ ]
109
+ # Get GPT3.5's answer
110
+ # Implement multi-turn dialogue by appending all_messages
111
+ final_response = get_completion_from_messages(all_messages + messages)
112
+ if debug:print("Step 4: Generated user answer")
113
+ # Add this round of information to historical messages
114
+ all_messages = all_messages + messages[1:]
115
+
116
+ # Step 5: Check if the output is compliant based on Moderation API
117
+ response = client.moderations.create(input=final_response)
118
+ moderation_output = response.results[0]
119
+
120
+ # Output is non-compliant
121
+ if moderation_output.flagged:
122
+ if debug: print("Step 5: Output rejected by Moderation")
123
+ return "Sorry, we cannot provide that information"
124
+
125
+ if debug: print("Step 5: Output passed Moderation check")
126
+
127
+ # Step 6: Model checks if the user's question is well answered
128
+ user_message = f"""
129
+ Customer message: {delimiter}{user_input}{delimiter}
130
+ Agent response: {delimiter}{final_response}{delimiter}
131
+
132
+ Does the response sufficiently answer the question? answer Yes or No
133
+ """
134
+ messages = [
135
+ {'role': 'system', 'content': system_message},
136
+ {'role': 'user', 'content': user_message}
137
+ ]
138
+ # Request model to evaluate the answer
139
+ evaluation_response = get_completion_from_messages(messages)
140
+ if debug: print("Step 6: Model evaluated the answer")
141
+
142
+ # Step 7: If evaluated as Y, output the answer; if evaluated as N, feedback that the answer will be manually corrected
143
+ if "Y" in evaluation_response: # Use 'in' to avoid the model possibly generating Yes
144
+ if debug: print("Step 7: Model approved the answer.")
145
+ return final_response, all_messages, category_and_product_response
146
+ else:
147
+ if debug: print("Step 7: Model disapproved the answer.")
148
+ neg_str = "I apologize, but I cannot provide the information you need. I will transfer you to a human customer service representative for further assistance."
149
+ return neg_str, all_messages
150
+
151
+ #Visual Interface
152
+ #log messages
153
+ messages_log = 'messages_log.json'
154
+
155
+ def log_messages(new_element, filepath):
156
+ # Update the messages_log with the new assistant response
157
+ filepath = 'messages_log.json'
158
+
159
+ try:
160
+ with open(filepath, "r") as file:
161
+ # Check if the file is empty
162
+ if file.read().strip() == "":
163
+ data = [] # Initialize with an empty list or dictionary as needed
164
+ else:
165
+ file.seek(0) # Move the cursor back to the start of the file
166
+ data = json.load(file)
167
+ except FileNotFoundError:
168
+ # If the file doesn't exist, start with an empty list or dictionary
169
+ data = []
170
+ except json.JSONDecodeError:
171
+ # If there is a JSON decoding error, handle it by initializing empty data
172
+ print("Error: The JSON file is not properly formatted.")
173
+ data = []
174
+
175
+ # Assuming the data is a list of items
176
+ data.append(new_element)
177
+
178
+ with open(filepath, "w") as file:
179
+ json.dump(data, file, indent=4)
180
+
181
+ # Initialize the context as an empty list to keep track of the conversation history
182
+ context = []
183
+
184
+ # Function to collect and process user messages
185
+ def collect_messages_en(input_text, debug=True):
186
+ global context # Use the global messages_log to track all messages
187
+
188
+ if debug: print(f"User Input = {input_text}")
189
+ if input_text == "":
190
+ return
191
+ #context = get_messages()
192
+ # Process the user input and get a response
193
+ response, context, product_category = process_user_message(input_text, context, debug=debug)
194
+ context.append({'role':'assistant', 'content':f"{response}"})
195
+
196
+ # Get the current timestamp
197
+ current_timestamp = datetime.now()
198
+ formatted_timestamp = current_timestamp.strftime("%Y-%m-%d %H:%M:%S")
199
+
200
+ #log the messages
201
+ log_messages({'time_stamp': formatted_timestamp, 'user_input': input_text, 'AI_response': response, 'metadata': product_category}, messages_log)
202
+ # Return the response to be displayed in the Gradio interface
203
+ return response
204
+
205
+ # Create a Gradio interface for interacting with the assistant
206
+ demo = gr.Interface(
207
+ fn=collect_messages_en,
208
+ inputs=gr.Textbox(lines=3, label="Inquiries", placeholder="Ask us anything..."),
209
+ outputs="text",
210
+ title="Customer Service Assistant",
211
+ description="Ask questions about products or services.",
212
+ )
213
+
214
+ demo.launch()
215
+
216
+ # user_input = "tell me about the smartx pro phone and the fotosnap camera, the dslr one. Also what tell me about your tvs"
217
+