krisha06 commited on
Commit
1e16169
·
verified ·
1 Parent(s): c7a13b5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +57 -85
app.py CHANGED
@@ -2,12 +2,10 @@ import streamlit as st
2
  import pandas as pd
3
  import chromadb
4
  from sentence_transformers import SentenceTransformer
5
- from transformers import pipeline, AutoTokenizer, AutoModelForCausalLM
6
  from PIL import Image
7
  from io import BytesIO
8
  import requests
9
- from huggingface_hub import login
10
-
11
 
12
  # --- 1. Load Recipes Dataset ---
13
  @st.cache_data
@@ -29,7 +27,7 @@ recipes_df = load_recipes()
29
  # --- 2. Load SentenceTransformer Model ---
30
  @st.cache_resource
31
  def load_embedding_model():
32
- return SentenceTransformer("all-mpnet-base-v2")
33
 
34
  embedding_model = load_embedding_model()
35
 
@@ -43,7 +41,7 @@ def get_sentence_transformer_embeddings(text):
43
 
44
  try:
45
  existing_data = collection.get()
46
- existing_ids = set(existing_data["ids"]) if existing_data and "ids" in existing_data else set()
47
  except Exception as e:
48
  st.error(f"⚠ ChromaDB Error: {e}")
49
  existing_ids = set()
@@ -54,78 +52,61 @@ for index, row in recipes_df.iterrows():
54
  continue
55
  embedding = get_sentence_transformer_embeddings(row["combined_text"])
56
  if embedding:
57
- collection.add(embeddings=[embedding], documents=[row["combined_text"]], ids=[recipe_id])
 
 
 
 
 
58
 
59
  # --- 5. Retrieve Similar Recipes ---
60
  def retrieve_recipes(query, top_k=3):
61
  query_embedding = get_sentence_transformer_embeddings(query)
62
  results = collection.query(query_embeddings=[query_embedding], n_results=top_k)
63
-
64
- if results and "ids" in results and results["ids"] and results["ids"][0]:
65
  recipe_indices = [int(id) for id in results["ids"][0] if id.isdigit()]
66
  return recipes_df.iloc[recipe_indices] if recipe_indices else None
67
  return None
68
 
69
-
70
  hf_token = st.secrets["key"]
71
  if hf_token is None:
72
  raise ValueError("Hugging Face token is missing. Add it as a secret in your Space.")
73
- login(token=hf_token)
74
-
75
- # --- 6. Load Mistral-7B-Instruct ---
76
- @st.cache_resource
77
  @st.cache_resource
78
- def load_mistral_model():
79
- model_name = "mistralai/Mistral-7B-Instruct-v0.3"
80
- tokenizer = AutoTokenizer.from_pretrained(model_name, use_auth_token=True)
81
- model = AutoModelForCausalLM.from_pretrained(
82
- model_name, use_auth_token=True, trust_remote_code=True, device_map="auto")
83
- return pipeline("text-generation", model=model, tokenizer=tokenizer, max_new_tokens=150)
84
-
85
- mistral_model = load_mistral_model()
86
-
87
-
88
- # --- 7. Answer Question Using Mistral ---
89
- def answer_question(query, context=""):
90
- greetings = ["hi", "hello", "hey", "greetings", "how are you", "what's up"]
91
- query_cleaned = query.lower().strip()
92
-
93
- # Handle greetings
94
- if query_cleaned in greetings:
95
- return "Hello! I'm here to assist with recipes and food-related questions. 🍽️ What would you like to know?"
96
-
97
- # Retrieve relevant recipe
98
- related_recipes = retrieve_recipes(query, top_k=1)
99
- if related_recipes is None or related_recipes.empty:
100
- return "I specialize in recipes! 🍽️ Feel free to ask me about ingredients, cooking methods, or meal ideas. 😊"
101
-
102
- # If found, use its instructions as context
103
- context = related_recipes.iloc[0]['instructions']
104
- prompt = f"Context: {context}\n\nQuestion: {query}\nAnswer:"
105
-
106
- response = mistral_model(prompt)
107
- if isinstance(response, list) and response:
108
- return response[0].get("generated_text", "I'm not sure, but I can help with recipes! 😊").strip()
109
-
110
- return "I'm not sure, but I can help with recipes! 😊"
111
-
112
- # --- 8. Classify Query Type ---
113
  @st.cache_resource
114
  def load_classifier():
115
- return pipeline("zero-shot-classification", model="facebook/bart-large-mnli", use_auth_token=True)
116
 
117
  classifier = load_classifier()
118
 
119
- def classify_query(query):
120
- recipe_keywords = ["make", "cook", "bake", "recipe", "prepare"]
121
- if any(keyword in query.lower() for keyword in recipe_keywords):
122
- return "Recipe Search"
123
-
124
- labels = ["Q&A", "Recipe Search"]
125
  result = classifier(query, candidate_labels=labels, multi_label=False)
126
- return result.get("labels", ["Q&A"])[0]
 
 
 
127
 
128
- # --- 9. Display Image ---
 
 
 
 
 
 
 
 
 
129
  def display_image(image_url, recipe_name):
130
  try:
131
  if not isinstance(image_url, str) or not image_url.startswith("http"):
@@ -140,7 +121,7 @@ def display_image(image_url, recipe_name):
140
  st.image(placeholder_url, caption=recipe_name, use_container_width=True)
141
 
142
  # --- 10. Streamlit UI ---
143
- st.title("🍽️ AI Recipe & Q&A Assistant (Powered by Mistral-7B)")
144
 
145
  user_query = st.text_input("Enter your question or recipe search query:", "", key="main_query_input")
146
 
@@ -149,31 +130,22 @@ if "retrieved_recipes" not in st.session_state:
149
 
150
  if st.button("Ask AI"):
151
  if user_query:
152
- # Handle greetings separately
153
- greeting_response = answer_question(user_query)
154
- if greeting_response.startswith("Hello!"):
155
- st.subheader("🤖 AI Answer:")
156
- st.write(greeting_response)
157
- else:
158
- # Classify query
159
- intent = classify_query(user_query)
160
-
161
- if intent == "Q&A":
162
- st.subheader("🤖 AI Answer:")
163
- response = answer_question(user_query)
164
- st.write(response)
165
-
166
- elif intent == "Recipe Search":
167
- retrieved_recipes = retrieve_recipes(user_query)
168
- if retrieved_recipes is not None and not retrieved_recipes.empty:
169
- st.session_state["retrieved_recipes"] = retrieved_recipes
170
- st.subheader("🍴 Found Recipes:")
171
- for index, recipe in retrieved_recipes.iterrows():
172
- st.markdown(f"### {recipe['title']}")
173
- st.write(f"**Ingredients:** {recipe['ingredients']}")
174
- st.write(f"**Instructions:** {recipe['instructions']}")
175
- display_image(recipe.get('img_src', ''), recipe['title'])
176
- else:
177
- st.warning("⚠️ No relevant recipes found.")
178
  else:
179
- st.warning(" Unable to classify the query.")
 
 
 
 
2
  import pandas as pd
3
  import chromadb
4
  from sentence_transformers import SentenceTransformer
5
+ from transformers import pipeline, AutoModelForQuestionAnswering, AutoTokenizer
6
  from PIL import Image
7
  from io import BytesIO
8
  import requests
 
 
9
 
10
  # --- 1. Load Recipes Dataset ---
11
  @st.cache_data
 
27
  # --- 2. Load SentenceTransformer Model ---
28
  @st.cache_resource
29
  def load_embedding_model():
30
+ return SentenceTransformer("all-MiniLM-L6-v2") # Smaller & optimized model
31
 
32
  embedding_model = load_embedding_model()
33
 
 
41
 
42
  try:
43
  existing_data = collection.get()
44
+ existing_ids = set(existing_data.get("ids", [])) # Use `.get()` for safety
45
  except Exception as e:
46
  st.error(f"⚠ ChromaDB Error: {e}")
47
  existing_ids = set()
 
52
  continue
53
  embedding = get_sentence_transformer_embeddings(row["combined_text"])
54
  if embedding:
55
+ collection.add(
56
+ embeddings=[embedding],
57
+ documents=[row["combined_text"]],
58
+ ids=[recipe_id],
59
+ metadatas=[{"title": row["title"], "ingredients": row["ingredients"], "instructions": row["instructions"], "img_src": row["img_src"]}]
60
+ )
61
 
62
  # --- 5. Retrieve Similar Recipes ---
63
  def retrieve_recipes(query, top_k=3):
64
  query_embedding = get_sentence_transformer_embeddings(query)
65
  results = collection.query(query_embeddings=[query_embedding], n_results=top_k)
66
+
67
+ if results and results.get("ids"):
68
  recipe_indices = [int(id) for id in results["ids"][0] if id.isdigit()]
69
  return recipes_df.iloc[recipe_indices] if recipe_indices else None
70
  return None
71
 
 
72
  hf_token = st.secrets["key"]
73
  if hf_token is None:
74
  raise ValueError("Hugging Face token is missing. Add it as a secret in your Space.")
75
+ login(token=hf_token)
76
+
77
+ # --- 6. Load LLM Model (Better Model for Generation) ---
 
78
  @st.cache_resource
79
+ def load_llm_model():
80
+ return pipeline("text-generation", model="mistralai/Mistral-7B-Instruct-v0.3")
81
+
82
+ llm_model = load_llm_model()
83
+
84
+ # --- 7. Load Classifier ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
  @st.cache_resource
86
  def load_classifier():
87
+ return pipeline("zero-shot-classification", model="facebook/bart-large-mnli")
88
 
89
  classifier = load_classifier()
90
 
91
+ # --- 8. Query Classification ---
92
+ def is_food_related(query):
93
+ labels = ["Food & Cooking", "General Knowledge", "Science", "Technology"]
 
 
 
94
  result = classifier(query, candidate_labels=labels, multi_label=False)
95
+ return result["labels"][0] == "Food & Cooking"
96
+
97
+ def generate_recipe(query):
98
+ related_recipes = retrieve_recipes(query, top_k=2)
99
 
100
+ if not related_recipes or related_recipes.empty:
101
+ return "I couldn't find a matching recipe, but let me create one for you!"
102
+
103
+ base_text = "\n".join([f"- {r['title']}: {r['ingredients']}" for _, r in related_recipes.iterrows()])
104
+ full_prompt = f"Create a unique recipe using these ingredients: {query}.\n\nReference recipes:\n{base_text}"
105
+
106
+ response = llm_model(full_prompt, max_length=200, num_return_sequences=1)
107
+ return response[0]["generated_text"]
108
+
109
+ # --- 9. Display Image Function ---
110
  def display_image(image_url, recipe_name):
111
  try:
112
  if not isinstance(image_url, str) or not image_url.startswith("http"):
 
121
  st.image(placeholder_url, caption=recipe_name, use_container_width=True)
122
 
123
  # --- 10. Streamlit UI ---
124
+ st.title("🍽️ AI Recipe & Q&A Assistant")
125
 
126
  user_query = st.text_input("Enter your question or recipe search query:", "", key="main_query_input")
127
 
 
130
 
131
  if st.button("Ask AI"):
132
  if user_query:
133
+ if is_food_related(user_query): # Check if it's food-related
134
+ st.subheader("🤖 AI Response:")
135
+ response = generate_recipe(user_query)
136
+ st.write(response)
137
+
138
+ retrieved_recipes = retrieve_recipes(user_query)
139
+ if retrieved_recipes is not None and not retrieved_recipes.empty:
140
+ st.session_state["retrieved_recipes"] = retrieved_recipes
141
+ st.subheader("🍴 Found Recipes:")
142
+ for _, recipe in retrieved_recipes.iterrows():
143
+ st.markdown(f"### {recipe['title']}")
144
+ st.write(f"**Ingredients:** {recipe['ingredients']}")
145
+ st.write(f"**Instructions:** {recipe['instructions']}")
146
+ display_image(recipe.get('img_src', ''), recipe['title'])
 
 
 
 
 
 
 
 
 
 
 
 
147
  else:
148
+ st.warning("⚠️ No relevant recipes found.")
149
+ else:
150
+ st.subheader("🤖 AI Answer:")
151
+ st.write("I specialize in food-related topics! 🍽️ Please ask me about recipes, cooking methods, or ingredients.")