Spaces:
Runtime error
Runtime error
Initial Model
Browse files- app.py +61 -0
- chain.py +50 -0
- images/octo.jpeg +0 -0
- ingest.py +74 -0
- requirement.txt +10 -0
app.py
ADDED
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import pickle
|
3 |
+
from chain import get_chain
|
4 |
+
|
5 |
+
|
6 |
+
with open("db.pkl", "rb") as f:
|
7 |
+
global vectorstore
|
8 |
+
vectorstore = pickle.load(f)
|
9 |
+
|
10 |
+
chain = get_chain()
|
11 |
+
|
12 |
+
def chat(inp, history):
|
13 |
+
history = history or []
|
14 |
+
output = chain({'input_documents': vectorstore.similarity_search(inp, k=4), 'query': inp}, return_only_outputs=True)
|
15 |
+
response = output['output_text']
|
16 |
+
history.append((inp, response))
|
17 |
+
return history, history
|
18 |
+
|
19 |
+
|
20 |
+
block = gr.Blocks(css=".gradio-container {background-color: lightgray}")
|
21 |
+
|
22 |
+
with block:
|
23 |
+
with gr.Row():
|
24 |
+
with gr.Column(scale=1):
|
25 |
+
# gr.Markdown("""<img src=https://huggingface.co/spaces/.jpeg></left>""")
|
26 |
+
gr.Markdown("""<img alt="Image" title="icon" src="./images/octo.jpeg" />""")
|
27 |
+
with gr.Column(scale=15):
|
28 |
+
gr.Markdown("<h1><left>Your Beer Sommelier</left></h1>")
|
29 |
+
gr.Markdown("""<h3><left> Your friendly beer sommelier is here to help you choose the right beer for you!</left></h3>""")
|
30 |
+
|
31 |
+
chatbot = gr.Chatbot()
|
32 |
+
|
33 |
+
with gr.Row():
|
34 |
+
message = gr.Textbox(
|
35 |
+
label="What's your question?",
|
36 |
+
placeholder="Do you have any recommendations for IPA with tropical fruite flavors?",
|
37 |
+
lines=1,
|
38 |
+
)
|
39 |
+
with gr.Row():
|
40 |
+
submit = gr.Button(value="Send", variant="secondary", size="lg")
|
41 |
+
|
42 |
+
gr.Examples(
|
43 |
+
examples=[
|
44 |
+
"What does Bock taste like? Do you recommend it?",
|
45 |
+
"I like Lagunitas IPA. Do you have anything similar?",
|
46 |
+
"Do you have any recommendations for Pilsner?",
|
47 |
+
"What kind of German beers do you have?"
|
48 |
+
],
|
49 |
+
inputs=message,
|
50 |
+
)
|
51 |
+
|
52 |
+
state = gr.State()
|
53 |
+
|
54 |
+
message.submit(chat, inputs=[message, state], outputs=[chatbot, state])
|
55 |
+
message.submit(lambda x: gr.update(value=''), [], [message])
|
56 |
+
|
57 |
+
submit.click(chat, inputs=[message, state], outputs=[chatbot, state])
|
58 |
+
submit.click(lambda x: gr.update(value=''), [], [message])
|
59 |
+
|
60 |
+
|
61 |
+
block.launch(debug=True, share=True)
|
chain.py
ADDED
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""Generate QA Chain to answer the question given matches (db)"""
|
2 |
+
import os
|
3 |
+
import openai
|
4 |
+
from langchain.chains.question_answering import load_qa_chain
|
5 |
+
from langchain.chat_models import ChatOpenAI
|
6 |
+
from langchain.llms import OpenAI
|
7 |
+
from langchain.memory import ConversationBufferMemory, ConversationBufferWindowMemory
|
8 |
+
from langchain.prompts import PromptTemplate
|
9 |
+
from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler
|
10 |
+
|
11 |
+
openai.api_key = os.environ['OPENAI_API_KEY']
|
12 |
+
|
13 |
+
def get_chain():
|
14 |
+
template = """
|
15 |
+
You are a ChatBot at a restaurant with expertise in beers and good at making recommendations based on the user's preferences.
|
16 |
+
You are a given a context delimited by "=========", which is extracted part of the restaurant's beer list.
|
17 |
+
Customer's question is given below delimited by "```````".
|
18 |
+
|
19 |
+
Based on the context, question and chat history, please respond in a friendly, conversational manner based on the context, describing features of beers.
|
20 |
+
When asked to make recommendations, make three to four. Do not mention ABV or IBU unless asked about it. Remember you are trying to promote your beers.
|
21 |
+
|
22 |
+
If asked about something that is not related to beers in any absolute way, say you are only good at recommending beers in a witty way and redirect the conversation
|
23 |
+
by asking about customer's preferences such as beer style, flavor, etc..
|
24 |
+
|
25 |
+
If you don't find the answer to the user's question with the context provided to you below,
|
26 |
+
answer that you don't have the requested beer and ask about customer's preferences such as beer style, flavor, etc..
|
27 |
+
Finish by proposing your help for anything else.
|
28 |
+
|
29 |
+
CONTEXT:
|
30 |
+
=========
|
31 |
+
{context}
|
32 |
+
=========
|
33 |
+
|
34 |
+
QUESTION:
|
35 |
+
````````
|
36 |
+
{query}
|
37 |
+
````````
|
38 |
+
CHAT HISTORY:
|
39 |
+
{chat_history}
|
40 |
+
|
41 |
+
ANSWER:
|
42 |
+
"""
|
43 |
+
|
44 |
+
prompt = PromptTemplate(input_variables=["chat_history", "query", "context"], template=template)
|
45 |
+
memory = ConversationBufferMemory(memory_key="chat_history", input_key="query")
|
46 |
+
chat = ChatOpenAI(temperature=0, streaming=True)
|
47 |
+
|
48 |
+
chain = load_qa_chain(llm=chat, chain_type="stuff", memory=memory, prompt=prompt)
|
49 |
+
|
50 |
+
return chain
|
images/octo.jpeg
ADDED
ingest.py
ADDED
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""Scrape selected data from the 'untapped' website, put them in a list of dictionaries,
|
2 |
+
embed and store them into a vectorstore."""
|
3 |
+
|
4 |
+
import requests
|
5 |
+
import os
|
6 |
+
import openai
|
7 |
+
from bs4 import BeautifulSoup
|
8 |
+
from langchain.embeddings.openai import OpenAIEmbeddings
|
9 |
+
from langchain.embeddings import CohereEmbeddings, HuggingFaceHubEmbeddings
|
10 |
+
from langchain.vectorstores import FAISS, Annoy, DocArrayInMemorySearch
|
11 |
+
from langchain.document_loaders import CSVLoader
|
12 |
+
import csv
|
13 |
+
import pickle
|
14 |
+
|
15 |
+
openai.api_key = os.environ['OPENAI_API_KEY']
|
16 |
+
|
17 |
+
|
18 |
+
def ingest_data():
|
19 |
+
headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36'}
|
20 |
+
url='https://untappd.com/v/gourmet-haus-staudt/15392'
|
21 |
+
response = requests.get(url, headers=headers)
|
22 |
+
soup = BeautifulSoup(response.text, 'html.parser')
|
23 |
+
|
24 |
+
links = soup.find_all('a', attrs={'data-track':'menu', 'data-href': ":"})
|
25 |
+
|
26 |
+
beer_list = []
|
27 |
+
|
28 |
+
for link in links:
|
29 |
+
page_url = 'https://untappd.com' + link.get('href')
|
30 |
+
|
31 |
+
if page_url:
|
32 |
+
page_response = requests.get(page_url, headers=headers)
|
33 |
+
page_soup = BeautifulSoup(page_response.text, 'html.parser')
|
34 |
+
|
35 |
+
# Extract the "relevant" page content
|
36 |
+
box_info = page_soup.find('div', class_="box b_info")
|
37 |
+
|
38 |
+
if box_info:
|
39 |
+
name = box_info.find('h1').get_text()
|
40 |
+
brewery = box_info.find(class_="brewery").get_text().strip()
|
41 |
+
style = box_info.find(class_="style").get_text()
|
42 |
+
description = box_info.find(class_="beer-descrption-read-less")
|
43 |
+
description.find('a').extract()
|
44 |
+
description = description.get_text().strip()
|
45 |
+
abv = box_info.find(class_="abv").get_text().strip()
|
46 |
+
ibu = box_info.find(class_="ibu").get_text().strip()
|
47 |
+
ratings = box_info.find(class_="num").get_text().replace("(", "").replace(")", "")
|
48 |
+
n_ratings = box_info.find(class_="raters").get_text().strip()
|
49 |
+
|
50 |
+
beer_dict = {"name": name, "brewery": brewery, "style": style, "description": description, "alcohol_by_volume": abv, "ibu_bitterness_unit": ibu, "ratings": ratings, "n_ratings": n_ratings}
|
51 |
+
|
52 |
+
beer_list.append(beer_dict)
|
53 |
+
|
54 |
+
keys = beer_list[0].keys()
|
55 |
+
|
56 |
+
with open('beers.csv', 'w', newline='') as output_file:
|
57 |
+
dict_writer = csv.DictWriter(output_file, keys)
|
58 |
+
dict_writer.writeheader()
|
59 |
+
dict_writer.writerows(beer_list)
|
60 |
+
|
61 |
+
file = 'beers.csv'
|
62 |
+
loader = CSVLoader(file_path=file)
|
63 |
+
data = loader.load()
|
64 |
+
|
65 |
+
embeddings = OpenAIEmbeddings()
|
66 |
+
db = FAISS.from_documents(data, embeddings)
|
67 |
+
|
68 |
+
# Save vectorstore
|
69 |
+
|
70 |
+
with open("db.pkl", "wb") as f:
|
71 |
+
pickle.dump(db, f)
|
72 |
+
|
73 |
+
if __name__ == "__main__":
|
74 |
+
ingest_data()
|
requirement.txt
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
langchain
|
2 |
+
openai
|
3 |
+
python-dotenv
|
4 |
+
faiss-cpu
|
5 |
+
annoy
|
6 |
+
tiktoken
|
7 |
+
cohere
|
8 |
+
chromadb
|
9 |
+
beautifulsoup4
|
10 |
+
gradio
|