FosterSystemsDatabase commited on
Commit
e2f7220
·
verified ·
1 Parent(s): 350e78f

Add Gradio UI updates

Browse files

I hope this doesn't break it all!!!

Files changed (1) hide show
  1. app.py +53 -116
app.py CHANGED
@@ -1,5 +1,19 @@
1
  from unsloth import FastLanguageModel
2
  from peft import PeftModel
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
 
4
  # Load the base model with FastLanguageModel
5
  model, tokenizer = FastLanguageModel.from_pretrained(
@@ -8,212 +22,135 @@ model, tokenizer = FastLanguageModel.from_pretrained(
8
  dtype=None,
9
  load_in_4bit=True
10
  )
11
-
12
- base_model_name = "unsloth/Llama-3.2-3B-Instruct"
13
  adapter_path = "FosterSystemsDatabase/model" # Path to LoRA adapter on Hugging Face
14
-
15
  model = PeftModel.from_pretrained(model, adapter_path)
16
 
17
- # Code for processing a query
18
- import pandas as pd
19
- from unsloth.chat_templates import get_chat_template
20
- from sklearn.feature_extraction.text import TfidfVectorizer
21
- from sklearn.metrics.pairwise import cosine_similarity
22
- from sentence_transformers import SentenceTransformer, util
23
- import nltk
24
-
25
- # Ensure you have NLTK stopwords downloaded
26
- nltk.download("stopwords")
27
- from nltk.corpus import stopwords
28
-
29
- # Step 1: Load the CSV file
30
  file_path = 'Clean Missouri Data.csv'
31
  df = pd.read_csv(file_path, encoding='MacRoman')
32
 
33
- # Step 2: Define a function to search relevant policies based on the user's query using cosine similarity
34
- def search_relevant_policies(query, df, top_n=10, max_chars = 40000):
35
  # Convert policies into a TF-IDF matrix
36
  tfidf = TfidfVectorizer(stop_words='english')
37
  tfidf_matrix = tfidf.fit_transform(df['Content'])
38
-
39
- # Get the query as a TF-IDF vector
40
  query_vector = tfidf.transform([query])
41
-
42
- # Calculate cosine similarity between query and policies
43
  cosine_sim = cosine_similarity(query_vector, tfidf_matrix).flatten()
44
-
45
  # Get the top N relevant policies
46
- top_indices = cosine_sim.argsort()[-top_n:][::-1]
47
- relevant_policies = df.iloc[top_indices]
48
-
49
  top_indices = cosine_sim.argsort()[-top_n:][::-1]
50
  relevant_policies = df.iloc[top_indices].copy()
51
 
52
  # Ensure total text is capped at max_chars
53
  char_count = 0
54
  valid_indices = []
55
-
56
  for idx, row in relevant_policies.iterrows():
57
  content_length = len(row["Content"])
58
-
59
- # If adding this content exceeds max_chars, stop adding any further policies
60
  if char_count + content_length > max_chars:
61
  break
62
-
63
- # Otherwise, keep this policy
64
  char_count += content_length
65
  valid_indices.append(idx)
66
-
67
- # Filter the dataframe to only include valid rows
68
  truncated_policies = relevant_policies.loc[valid_indices]
69
-
70
  return truncated_policies
71
 
72
-
73
  def get_content_after_query(response_text, query):
74
- # Find the position of the query within the response text
75
  query_position = response_text.lower().find(query.lower())
76
  if query_position != -1:
77
- # Return the content after the query position
78
  res = response_text[query_position + len(query):].strip()
79
  return res[11:]
80
  else:
81
- # If the query is not found, return the full response text as a fallback
82
  return response_text.strip()
83
 
84
-
85
- def process_query(query,tokenizer):
86
-
87
  relevant_policies = search_relevant_policies(query, df)
88
-
89
- # Step 5: Combine the relevant policies with the user's query for the model
90
- formatted_policies = []
91
- for index, row in relevant_policies.iterrows():
92
- # formatted_policy = f"Title: {row['Title']}\nTerritory: {row['Territory']}\nType: {row['Type']}\nYear: {row['Year']}\nCategory: {row['Category']}\nFrom: {row['From']}\nTo: {row['To']}\nContent: {row['Content']}\nLink: {row['Link to Content']}\n"
93
- # formatted_policies.append(formatted_policy)
94
- formatted_policies.append(row['Content'])
95
  relevant_policy_text = "\n\n".join(formatted_policies)
96
-
97
- # Messages with relevant policies for the model
98
  messages_with_relevant_policies = [
99
  {"role": "system", "content": relevant_policy_text},
100
  {"role": "user", "content": query},
101
  ]
102
-
103
- # Step 6: Apply chat template and tokenize
104
- tokenizer = get_chat_template(
105
- tokenizer,
106
- chat_template="llama-3.1",
107
- )
108
  inputs = tokenizer.apply_chat_template(
109
  messages_with_relevant_policies,
110
  tokenize=True,
111
  add_generation_prompt=True,
112
  return_tensors="pt"
113
  ).to("cuda")
114
-
115
  FastLanguageModel.for_inference(model)
116
  outputs = model.generate(input_ids=inputs, max_new_tokens=512, use_cache=True, temperature=0.7, min_p=0.1)
117
-
118
- # Step 7: Decode the output
119
  generated_response = tokenizer.batch_decode(outputs, skip_special_tokens=True)[0]
120
  response = get_content_after_query(generated_response, query)
121
-
122
- # Step 8: Rank the top 10 policies using SBERT for the final link
123
- # Load SBERT model
124
- model_sbert = SentenceTransformer('all-MiniLM-L6-v2') # You can choose another SBERT model if desired
125
-
126
- # Encode the generated response using SBERT
127
  response_embedding = model_sbert.encode(generated_response, convert_to_tensor=True)
128
-
129
- # Encode each policy in the top 10 list
130
  policy_embeddings = model_sbert.encode(relevant_policies['Content'].tolist(), convert_to_tensor=True)
131
-
132
- # Calculate cosine similarities between the generated response and each policy embedding
133
  cosine_similarities = util.cos_sim(response_embedding, policy_embeddings).flatten()
134
-
135
- # Identify the policy with the highest SBERT cosine similarity score
136
  most_relevant_index = cosine_similarities.argmax().item()
137
  most_relevant_link = relevant_policies.iloc[most_relevant_index]['Link to Content']
138
-
139
- # Print the link to the most relevant source
140
  return {
141
  "response": response,
142
  "most_relevant_link": most_relevant_link
143
  }
144
 
145
-
146
- # Load Google Sheets to store results
147
- import json
148
- from google.oauth2.service_account import Credentials
149
- import gspread
150
- import pandas as pd
151
-
152
- # Load the service account JSON
153
- json_file_path = "fostercare-449201-85282f81c3b7.json" # Load the credentials for the service account
154
  with open(json_file_path, 'r') as file:
155
  service_account_data = json.load(file)
156
-
157
- # Authenticate using the loaded service account data
158
  scopes = ["https://www.googleapis.com/auth/spreadsheets", "https://www.googleapis.com/auth/drive"]
159
  creds = Credentials.from_service_account_info(service_account_data, scopes=scopes)
160
  client = gspread.authorize(creds)
161
-
162
- # Open the shared Google Sheet by name
163
  spreadsheet = client.open("Fostercare Responses").sheet1
164
 
165
- # Link to Google Sheet
166
- # https://docs.google.com/spreadsheets/d/1cUwgYxLaCGnXnSjS2LJN7Fr0xnJ8_zlGRI6RpCFVvMQ/
167
-
168
- # Code to set up Gradio GUI
169
- import gradio as gr
170
-
171
  def greet(query):
172
  result_1 = process_query(query, tokenizer)
173
- content_after_query_1 = result_1["response"]
174
-
175
  result_2 = process_query(query, tokenizer)
176
- content_after_query_2 = result_2["response"]
177
-
178
- return [content_after_query_1, content_after_query_2]
179
 
180
- def choose_preference(name, output1, output2, preference, query):
181
  if not name:
182
- return "Please enter your name before submitting."
183
-
 
 
184
  if preference == "Output 1":
185
- new_row = [query, output1, output2, name]
186
  spreadsheet.append_row(new_row)
187
  return f"You preferred: Output 1 - {output1}"
188
  elif preference == "Output 2":
189
- new_row = [query, output2, output1, name]
190
  spreadsheet.append_row(new_row)
191
  return f"You preferred: Output 2 - {output2}"
192
  else:
193
  return "No preference selected."
194
 
195
- # Define the interface
196
  with gr.Blocks() as demo:
197
- # Name input
198
  name_input = gr.Textbox(label="Enter your name")
199
-
200
- # Input for query
201
  query_input = gr.Textbox(label="Enter your query")
202
-
203
- # Outputs
204
  output_1 = gr.Textbox(label="Output 1", interactive=False)
205
  output_2 = gr.Textbox(label="Output 2", interactive=False)
206
-
207
- # Preference selection
208
  preference = gr.Radio(["Output 1", "Output 2"], label="Choose your preferred output")
 
209
  preference_result = gr.Textbox(label="Your Preference", interactive=False)
210
-
211
- # Buttons
212
- generate_button = gr.Button("Generate Outputs")
213
  submit_button = gr.Button("Submit Preference")
214
-
215
- # Link actions to buttons
216
  generate_button.click(greet, inputs=query_input, outputs=[output_1, output_2])
217
- submit_button.click(choose_preference, inputs=[name_input, output_1, output_2, preference, query_input], outputs=preference_result)
 
 
 
 
 
 
 
 
218
 
219
  demo.launch()
 
1
  from unsloth import FastLanguageModel
2
  from peft import PeftModel
3
+ import pandas as pd
4
+ from unsloth.chat_templates import get_chat_template
5
+ from sklearn.feature_extraction.text import TfidfVectorizer
6
+ from sklearn.metrics.pairwise import cosine_similarity
7
+ from sentence_transformers import SentenceTransformer, util
8
+ import nltk
9
+ import json
10
+ from google.oauth2.service_account import Credentials
11
+ import gspread
12
+ import gradio as gr
13
+
14
+ # Download stopwords
15
+ nltk.download("stopwords")
16
+ from nltk.corpus import stopwords
17
 
18
  # Load the base model with FastLanguageModel
19
  model, tokenizer = FastLanguageModel.from_pretrained(
 
22
  dtype=None,
23
  load_in_4bit=True
24
  )
 
 
25
  adapter_path = "FosterSystemsDatabase/model" # Path to LoRA adapter on Hugging Face
 
26
  model = PeftModel.from_pretrained(model, adapter_path)
27
 
28
+ # Load CSV data
 
 
 
 
 
 
 
 
 
 
 
 
29
  file_path = 'Clean Missouri Data.csv'
30
  df = pd.read_csv(file_path, encoding='MacRoman')
31
 
32
+ def search_relevant_policies(query, df, top_n=10, max_chars=40000):
 
33
  # Convert policies into a TF-IDF matrix
34
  tfidf = TfidfVectorizer(stop_words='english')
35
  tfidf_matrix = tfidf.fit_transform(df['Content'])
 
 
36
  query_vector = tfidf.transform([query])
 
 
37
  cosine_sim = cosine_similarity(query_vector, tfidf_matrix).flatten()
38
+
39
  # Get the top N relevant policies
 
 
 
40
  top_indices = cosine_sim.argsort()[-top_n:][::-1]
41
  relevant_policies = df.iloc[top_indices].copy()
42
 
43
  # Ensure total text is capped at max_chars
44
  char_count = 0
45
  valid_indices = []
 
46
  for idx, row in relevant_policies.iterrows():
47
  content_length = len(row["Content"])
 
 
48
  if char_count + content_length > max_chars:
49
  break
 
 
50
  char_count += content_length
51
  valid_indices.append(idx)
52
+
 
53
  truncated_policies = relevant_policies.loc[valid_indices]
 
54
  return truncated_policies
55
 
 
56
  def get_content_after_query(response_text, query):
 
57
  query_position = response_text.lower().find(query.lower())
58
  if query_position != -1:
 
59
  res = response_text[query_position + len(query):].strip()
60
  return res[11:]
61
  else:
 
62
  return response_text.strip()
63
 
64
+ def process_query(query, tokenizer):
 
 
65
  relevant_policies = search_relevant_policies(query, df)
66
+ formatted_policies = [row['Content'] for _, row in relevant_policies.iterrows()]
 
 
 
 
 
 
67
  relevant_policy_text = "\n\n".join(formatted_policies)
68
+
 
69
  messages_with_relevant_policies = [
70
  {"role": "system", "content": relevant_policy_text},
71
  {"role": "user", "content": query},
72
  ]
73
+
74
+ tokenizer = get_chat_template(tokenizer, chat_template="llama-3.1")
 
 
 
 
75
  inputs = tokenizer.apply_chat_template(
76
  messages_with_relevant_policies,
77
  tokenize=True,
78
  add_generation_prompt=True,
79
  return_tensors="pt"
80
  ).to("cuda")
81
+
82
  FastLanguageModel.for_inference(model)
83
  outputs = model.generate(input_ids=inputs, max_new_tokens=512, use_cache=True, temperature=0.7, min_p=0.1)
 
 
84
  generated_response = tokenizer.batch_decode(outputs, skip_special_tokens=True)[0]
85
  response = get_content_after_query(generated_response, query)
86
+
87
+ # Rank the top policy using SBERT
88
+ model_sbert = SentenceTransformer('all-MiniLM-L6-v2')
 
 
 
89
  response_embedding = model_sbert.encode(generated_response, convert_to_tensor=True)
 
 
90
  policy_embeddings = model_sbert.encode(relevant_policies['Content'].tolist(), convert_to_tensor=True)
 
 
91
  cosine_similarities = util.cos_sim(response_embedding, policy_embeddings).flatten()
 
 
92
  most_relevant_index = cosine_similarities.argmax().item()
93
  most_relevant_link = relevant_policies.iloc[most_relevant_index]['Link to Content']
94
+
 
95
  return {
96
  "response": response,
97
  "most_relevant_link": most_relevant_link
98
  }
99
 
100
+ # Set up Google Sheets
101
+ json_file_path = "fostercare-449201-85282f81c3b7.json"
 
 
 
 
 
 
 
102
  with open(json_file_path, 'r') as file:
103
  service_account_data = json.load(file)
 
 
104
  scopes = ["https://www.googleapis.com/auth/spreadsheets", "https://www.googleapis.com/auth/drive"]
105
  creds = Credentials.from_service_account_info(service_account_data, scopes=scopes)
106
  client = gspread.authorize(creds)
 
 
107
  spreadsheet = client.open("Fostercare Responses").sheet1
108
 
109
+ # Gradio functions
 
 
 
 
 
110
  def greet(query):
111
  result_1 = process_query(query, tokenizer)
 
 
112
  result_2 = process_query(query, tokenizer)
113
+ return [result_1["response"], result_2["response"]]
 
 
114
 
115
+ def choose_preference(name, output1, output2, preference, query, broken):
116
  if not name:
117
+ return "Please enter your name before submitting."
118
+
119
+ broken_flag = "Yes" if broken else "No"
120
+
121
  if preference == "Output 1":
122
+ new_row = [query, output1, output2, name, broken_flag]
123
  spreadsheet.append_row(new_row)
124
  return f"You preferred: Output 1 - {output1}"
125
  elif preference == "Output 2":
126
+ new_row = [query, output2, output1, name, broken_flag]
127
  spreadsheet.append_row(new_row)
128
  return f"You preferred: Output 2 - {output2}"
129
  else:
130
  return "No preference selected."
131
 
132
+ # Gradio UI
133
  with gr.Blocks() as demo:
 
134
  name_input = gr.Textbox(label="Enter your name")
 
 
135
  query_input = gr.Textbox(label="Enter your query")
136
+ # "Generate Outputs" button is now placed right after the query input
137
+ generate_button = gr.Button("Generate Outputs")
138
  output_1 = gr.Textbox(label="Output 1", interactive=False)
139
  output_2 = gr.Textbox(label="Output 2", interactive=False)
 
 
140
  preference = gr.Radio(["Output 1", "Output 2"], label="Choose your preferred output")
141
+ broken_flag = gr.Checkbox(label="Mark as Broken Answer")
142
  preference_result = gr.Textbox(label="Your Preference", interactive=False)
 
 
 
143
  submit_button = gr.Button("Submit Preference")
144
+
 
145
  generate_button.click(greet, inputs=query_input, outputs=[output_1, output_2])
146
+ submit_button.click(
147
+ choose_preference,
148
+ inputs=[name_input, output_1, output_2, preference, query_input, broken_flag],
149
+ outputs=preference_result
150
+ ).then(
151
+ fn=lambda: ("", "", "", "", "", False, ""),
152
+ inputs=[],
153
+ outputs=[name_input, query_input, output_1, output_2, preference, broken_flag, preference_result]
154
+ )
155
 
156
  demo.launch()