Copain22 commited on
Commit
5d4d3e2
·
verified ·
1 Parent(s): 2f49d9a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +85 -108
app.py CHANGED
@@ -1,118 +1,95 @@
1
- import os
 
2
  from pathlib import Path
3
- import streamlit as st
4
- from langchain_community.embeddings import HuggingFaceEmbeddings
5
- from langchain_community.vectorstores import FAISS
6
- from langchain.chains import ConversationalRetrievalChain
7
- from langchain_community.llms import HuggingFaceHub
8
- from langchain.memory import ConversationBufferMemory
9
- from langchain.text_splitter import RecursiveCharacterTextSplitter
10
- from langchain_community.document_loaders import PyMuPDFLoader
11
 
12
- # Initialize session state FIRST (before any other Streamlit operations)
13
- def initialize_session_state():
14
- if 'messages' not in st.session_state:
15
- st.session_state.messages = [{
16
- "role": "assistant",
17
- "content": "Hi! Welcome to Café Eleven. What would you like to order today?"
18
- }]
19
 
20
- # Main application function
21
- def main():
22
- initialize_session_state()
23
-
24
- # App configuration
25
- st.set_page_config(page_title="Café Eleven", page_icon="☕")
26
- st.title("☕ Café Eleven Ordering Assistant")
27
-
28
- # Display chat messages
29
- for message in st.session_state.messages:
30
- with st.chat_message(message["role"]):
31
- st.write(message["content"])
32
-
33
- # Chat processing functions
34
- @st.cache_resource
35
- def setup_chain():
36
- pdf_files = list(Path(".").glob("*.pdf"))
37
- if not pdf_files:
38
- st.error("No PDF menus found! Please upload some.")
39
- st.stop()
40
-
41
- # Process all PDFs
42
- docs = []
43
- for pdf in pdf_files:
44
- loader = PyMuPDFLoader(str(pdf))
45
- docs.extend(loader.load())
46
-
47
- # Split text
48
- text_splitter = RecursiveCharacterTextSplitter(
49
- chunk_size=1000,
50
- chunk_overlap=200
51
- )
52
- splits = text_splitter.split_documents(docs)
53
-
54
- # Create embeddings
55
- embeddings = HuggingFaceEmbeddings(
56
- model_name="sentence-transformers/all-mpnet-base-v2"
57
- )
58
- vectorstore = FAISS.from_documents(splits, embeddings)
59
-
60
- # Setup LLM
61
- llm = HuggingFaceHub(
62
- repo_id="meta-llama/Llama-2-7b-chat-hf",
63
- huggingfacehub_api_token=os.environ.get("HF_TOKEN", ""),
64
  model_kwargs={
65
- "temperature": 0.2,
66
- "max_length": 256
67
- }
 
 
 
68
  )
69
-
70
- # Create conversation chain
71
- return ConversationalRetrievalChain.from_llm(
72
- llm=llm,
73
- retriever=vectorstore.as_retriever(),
74
- memory=ConversationBufferMemory(
75
- memory_key="chat_history",
76
- return_messages=True
77
- )
78
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
 
80
- # Handle chat input
81
- if prompt := st.chat_input("What would you like to order?"):
82
- # Add user message
83
- st.session_state.messages.append({"role": "user", "content": prompt})
84
- with st.chat_message("user"):
85
- st.write(prompt)
86
-
87
- # Generate response
88
- with st.chat_message("assistant"):
89
- with st.spinner("Preparing your order..."):
90
- try:
91
- chain = setup_chain()
92
- response = chain({"question": prompt})["answer"]
93
- st.write(response)
94
- st.session_state.messages.append({
95
- "role": "assistant",
96
- "content": response
97
- })
98
- except Exception as e:
99
- st.error(f"Error: {str(e)}")
100
 
101
- # PDF upload in sidebar
102
- with st.sidebar:
103
- st.header("Menu Management")
104
- uploaded_files = st.file_uploader(
105
- "Upload menu PDFs",
106
- type="pdf",
107
- accept_multiple_files=True
108
- )
109
- if uploaded_files:
110
- for file in uploaded_files:
111
- with open(file.name, "wb") as f:
112
- f.write(file.getbuffer())
113
- st.success(f"Uploaded {len(uploaded_files)} new menu(s)")
114
- st.cache_resource.clear()
115
 
116
- # Entry point for Hugging Face Spaces
117
  if __name__ == "__main__":
118
- main()
 
1
+ # ---------- 0. Imports & constants ----------
2
+ import os, torch, gradio as gr
3
  from pathlib import Path
4
+ from huggingface_hub import login
 
 
 
 
 
 
 
5
 
6
+ from llama_index.core import (
7
+ VectorStoreIndex, SimpleDirectoryReader, Settings, PromptTemplate
8
+ )
9
+ from llama_index.core.memory import ChatMemoryBuffer
10
+ from llama_index.llms.huggingface import HuggingFaceLLM
11
+ from llama_index.embeddings.langchain import LangchainEmbedding
12
+ from langchain.embeddings.huggingface import HuggingFaceEmbeddings
13
 
14
+ SYSTEM_PROMPT = """
15
+ You are a friendly café assistant for Café Eleven. Your job is to:
16
+ 1. Greet the customer warmly
17
+ 2. Help them order food/drinks from our menu
18
+ 3. Answer questions about ingredients, preparation, etc.
19
+ 4. Process special requests (allergies, modifications)
20
+ 5. Provide a friendly farewell
21
+
22
+ Always be polite and helpful!"""
23
+
24
+ WRAPPER_PROMPT = PromptTemplate(
25
+ "[INST]<<SYS>>\n" + SYSTEM_PROMPT + "\n<</SYS>>\n\n{query_str} [/INST]"
26
+ )
27
+
28
+ login(token=os.environ["HF_TOKEN"])
29
+
30
+ # ---------- 1. Pre-load documents & build the vector index (CPU-safe) ----------
31
+ docs = SimpleDirectoryReader(
32
+ input_files=[str(p) for p in Path(".").glob("*.pdf")]
33
+ ).load_data()
34
+ embed_model = LangchainEmbedding(
35
+ HuggingFaceEmbeddings(model_name="sentence-transformers/all-mpnet-base-v2")
36
+ )
37
+ Settings.embed_model = embed_model
38
+ Settings.chunk_size = 512
39
+
40
+ index = VectorStoreIndex.from_documents(docs)
41
+
42
+ # ---------- 2. Lazy, singleton chat-engine ----------
43
+ _state = {"chat_engine": None} # filled on first request
44
+
45
+ def get_chat_engine():
46
+ if _state["chat_engine"] is None:
47
+ llm = HuggingFaceLLM(
48
+ tokenizer_name="meta-llama/Llama-2-7b-chat-hf",
49
+ model_name="meta-llama/Llama-2-7b-chat-hf",
50
+ context_window=3900,
51
+ max_new_tokens=256,
52
+ generate_kwargs={"temperature":0.2, "do_sample":True},
53
+ device_map="auto",
 
 
 
 
54
  model_kwargs={
55
+ "torch_dtype": torch.float16,
56
+ "load_in_4bit": True,
57
+ "use_auth_token": os.environ["HF_TOKEN"]
58
+ },
59
+ system_prompt=SYSTEM_PROMPT,
60
+ query_wrapper_prompt=WRAPPER_PROMPT,
61
  )
62
+ Settings.llm = llm
63
+
64
+ memory = ChatMemoryBuffer.from_defaults(token_limit=2000)
65
+ _state["chat_engine"] = index.as_chat_engine(
66
+ chat_mode="condense_plus_context",
67
+ memory=memory,
68
+ system_prompt=SYSTEM_PROMPT,
 
 
69
  )
70
+ return _state["chat_engine"]
71
+
72
+ # ---------- 3. Gradio UI ----------
73
+ def respond(message, chat_history):
74
+ if message.lower().strip() in {"quit", "exit", "done"}:
75
+ return "Thank you for your order! We'll see you soon.", chat_history
76
+
77
+ engine = get_chat_engine()
78
+ response = engine.chat(message).response
79
+ chat_history.append((message, response))
80
+ return "", chat_history
81
+
82
+ with gr.Blocks(title="Café Eleven Chat") as demo:
83
+ gr.Markdown("## ☕ Café Eleven Ordering Assistant")
84
+ gr.Markdown("Type your order or question below. Type 'quit' to end the chat.")
85
 
86
+ chatbot = gr.Chatbot(height=500)
87
+ msg = gr.Textbox(label="Your message", placeholder="Hi, I'd like a latte...")
88
+ clear = gr.Button("Clear Chat")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
 
90
+ msg.submit(respond, [msg, chatbot], [msg, chatbot])
91
+ clear.click(lambda: None, None, chatbot, queue=False)
 
 
 
 
 
 
 
 
 
 
 
 
92
 
93
+ # For public sharing
94
  if __name__ == "__main__":
95
+ demo.launch(share=True)