Spaces:
Sleeping
Sleeping
complete app.py
Browse files
app.py
CHANGED
@@ -1,107 +1,139 @@
|
|
1 |
-
import
|
2 |
-
from
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
|
4 |
import gradio as gr
|
5 |
-
from langchain.chains import ConversationChain
|
6 |
-
from langchain.llms import OpenAI
|
7 |
-
from threading import Lock
|
8 |
-
|
9 |
-
|
10 |
-
def load_chain():
|
11 |
-
"""Logic for loading the chain you want to use should go here."""
|
12 |
-
llm = OpenAI(temperature=0)
|
13 |
-
chain = ConversationChain(llm=llm)
|
14 |
-
return chain
|
15 |
-
|
16 |
-
|
17 |
-
def set_openai_api_key(api_key: str):
|
18 |
-
"""Set the api key and return chain.
|
19 |
-
|
20 |
-
If no api_key, then None is returned.
|
21 |
-
"""
|
22 |
-
if api_key:
|
23 |
-
os.environ["OPENAI_API_KEY"] = api_key
|
24 |
-
chain = load_chain()
|
25 |
-
os.environ["OPENAI_API_KEY"] = ""
|
26 |
-
return chain
|
27 |
-
|
28 |
-
class ChatWrapper:
|
29 |
-
|
30 |
-
def __init__(self):
|
31 |
-
self.lock = Lock()
|
32 |
-
def __call__(
|
33 |
-
self, api_key: str, inp: str, history: Optional[Tuple[str, str]], chain: Optional[ConversationChain]
|
34 |
-
):
|
35 |
-
"""Execute the chat functionality."""
|
36 |
-
self.lock.acquire()
|
37 |
-
try:
|
38 |
-
history = history or []
|
39 |
-
# If chain is None, that is because no API key was provided.
|
40 |
-
if chain is None:
|
41 |
-
history.append((inp, "Please paste your OpenAI key to use"))
|
42 |
-
return history, history
|
43 |
-
# Set OpenAI key
|
44 |
-
import openai
|
45 |
-
openai.api_key = api_key
|
46 |
-
# Run chain and append input.
|
47 |
-
output = chain.run(input=inp)
|
48 |
-
history.append((inp, output))
|
49 |
-
except Exception as e:
|
50 |
-
raise e
|
51 |
-
finally:
|
52 |
-
self.lock.release()
|
53 |
-
return history, history
|
54 |
-
|
55 |
-
chat = ChatWrapper()
|
56 |
-
|
57 |
-
block = gr.Blocks(css=".gradio-container {background-color: lightgray}")
|
58 |
-
|
59 |
-
with block:
|
60 |
-
with gr.Row():
|
61 |
-
gr.Markdown("<h3><center>LangChain Demo</center></h3>")
|
62 |
-
|
63 |
-
openai_api_key_textbox = gr.Textbox(
|
64 |
-
placeholder="Paste your OpenAI API key (sk-...)",
|
65 |
-
show_label=False,
|
66 |
-
lines=1,
|
67 |
-
type="password",
|
68 |
-
)
|
69 |
|
70 |
-
|
|
|
71 |
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
77 |
)
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
87 |
)
|
|
|
88 |
|
89 |
-
|
|
|
90 |
|
91 |
-
|
92 |
-
|
93 |
-
)
|
94 |
|
95 |
-
|
96 |
-
|
|
|
97 |
|
98 |
-
|
99 |
-
|
|
|
100 |
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
105 |
)
|
|
|
106 |
|
107 |
-
|
|
|
|
1 |
+
from langchain.embeddings.openai import OpenAIEmbeddings
|
2 |
+
from langchain.vectorstores import Chroma
|
3 |
+
from langchain.text_splitter import RecursiveCharacterTextSplitter
|
4 |
+
from langchain.agents import AgentExecutor, Tool, load_tools
|
5 |
+
from langchain.chains import RetrievalQA, RetrievalQAWithSourcesChain, LLMChain, LLMMathChain
|
6 |
+
from langchain.chat_models import ChatOpenAI
|
7 |
+
from langchain.document_loaders import DirectoryLoader
|
8 |
+
from langchain.memory import ConversationBufferMemory
|
9 |
+
from langchain.utilities import WikipediaAPIWrapper
|
10 |
+
from langchain.agents import initialize_agent, AgentType
|
11 |
+
from langchain.document_loaders import WebBaseLoader
|
12 |
|
13 |
import gradio as gr
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
14 |
|
15 |
+
# Add presets for Gradio theme
|
16 |
+
from app_modules.presets import *
|
17 |
|
18 |
+
import os
|
19 |
+
os.environ["OPENAI_API_KEY"] = "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"
|
20 |
+
|
21 |
+
# Flag to load chroma store
|
22 |
+
flag_chroma = True
|
23 |
+
|
24 |
+
# Define the LLM chat model
|
25 |
+
#model = 'gpt-3.5-turbo'
|
26 |
+
model = 'gpt-4'
|
27 |
+
temperature = 0
|
28 |
+
llm = ChatOpenAI(temperature=temperature, model=model)
|
29 |
+
|
30 |
+
# Check flag to load vectorstore
|
31 |
+
if flag_chroma:
|
32 |
+
# Load an existing database
|
33 |
+
persist_dir = "./chroma"
|
34 |
+
embeddings = OpenAIEmbeddings()
|
35 |
+
vectorstore = Chroma(persist_directory=persist_dir, embedding_function=embeddings)
|
36 |
+
vectorstore.persist()
|
37 |
+
else:
|
38 |
+
# Document and sources loader
|
39 |
+
pdf_loader = DirectoryLoader('./Reports/', glob="**/*.pdf")
|
40 |
+
txt_loader = DirectoryLoader('./Reports/', glob="**/*.txt")
|
41 |
+
word_loader = DirectoryLoader('./Reports/', glob="**/*.docx")
|
42 |
+
web_based_loader = WebBaseLoader(["https://www.unwomen.org/en/what-we-do/ending-violence-against-women/faqs/types-of-violence", "https://2021.gho.unocha.org/global-trends/gender-and-gender-based-violence-humanitarian-action/"])
|
43 |
+
|
44 |
+
loaders = [pdf_loader, txt_loader, word_loader, web_based_loader]
|
45 |
+
docs = []
|
46 |
+
for loader in loaders:
|
47 |
+
docs.extend(loader.load())
|
48 |
+
|
49 |
+
# Text splitter
|
50 |
+
## If chunks are bigger than 1000, it recursively splits them until fitting them within size
|
51 |
+
text_splitter = RecursiveCharacterTextSplitter(
|
52 |
+
separators=["\n\n", "\n", ".", "!", "?", ",", " ", ""],
|
53 |
+
chunk_size = 1000,
|
54 |
+
chunk_overlap = 50
|
55 |
+
)
|
56 |
+
documents = text_splitter.split_documents(docs)
|
57 |
+
|
58 |
+
# Embed documents in Vectorstore
|
59 |
+
persist_dir = "chroma"
|
60 |
+
embeddings = OpenAIEmbeddings()
|
61 |
+
vectorstore = Chroma.from_documents(documents, embeddings, persist_directory=persist_dir)
|
62 |
+
vectorstore.persist()
|
63 |
+
|
64 |
+
# Create Retrieval Chain with sources
|
65 |
+
## It returns a dictionary with at least the 'answer' and the 'sources'
|
66 |
+
qa = RetrievalQAWithSourcesChain.from_chain_type(
|
67 |
+
llm=llm,
|
68 |
+
chain_type="stuff",
|
69 |
+
retriever=vectorstore.as_retriever(),
|
70 |
+
return_source_documents=True
|
71 |
)
|
72 |
+
|
73 |
+
# Define tools
|
74 |
+
wikipedia = WikipediaAPIWrapper()
|
75 |
+
|
76 |
+
tools = [
|
77 |
+
Tool(
|
78 |
+
name="GBV Q&A Bot System",
|
79 |
+
#func=qa,
|
80 |
+
func=lambda question: qa({"question": question}, return_only_outputs=True),
|
81 |
+
description="Useful for when you need to answer questions about the aspects asked. Input may be a partial or fully formed question.",
|
82 |
+
#return_direct=True, # use the agent as a router and directly return the result
|
83 |
+
),
|
84 |
+
Tool(
|
85 |
+
name='Wikipedia',
|
86 |
+
func=wikipedia.run,
|
87 |
+
description='You must only use this tool if you cannot find answers with the other tools. Useful for when you need to look for answers in the Wikipedia.'
|
88 |
)
|
89 |
+
]
|
90 |
|
91 |
+
# Create Buffer Memory
|
92 |
+
memory = ConversationBufferMemory(memory_key="chat_history", input_key='input', output_key="output", return_messages=True)
|
93 |
|
94 |
+
# Initialize Re-Act agent and create Agent Executor Chain
|
95 |
+
react = initialize_agent(tools, llm, agent=AgentType.CHAT_CONVERSATIONAL_REACT_DESCRIPTION, verbose=True, max_iterations=3, early_stopping_method='generate', memory=memory)
|
|
|
96 |
|
97 |
+
agent_chain = AgentExecutor.from_agent_and_tools(
|
98 |
+
agent=react.agent, tools=tools, verbose=True, memory=memory, return_intermediate_steps=True, return_source_documents=True, handle_parsing_errors=True
|
99 |
+
)
|
100 |
|
101 |
+
# Add custom CSS
|
102 |
+
with open("assets/custom.css", "r", encoding="utf-8") as f:
|
103 |
+
customCSS = f.read()
|
104 |
|
105 |
+
with gr.Blocks(css=customCSS, theme=small_and_beautiful_theme) as demo:
|
106 |
+
|
107 |
+
gr.Markdown(
|
108 |
+
"""
|
109 |
+
# 🦜🔗 Ask GBV Q&A Bot!
|
110 |
+
Start typing below to see the output.
|
111 |
+
"""
|
112 |
+
)
|
113 |
+
|
114 |
+
# Start chatbot with welcome from bot
|
115 |
+
chatbot = gr.Chatbot([(None,'How can I help you?')]).style(height=650)
|
116 |
+
msg = gr.Textbox()
|
117 |
+
clear = gr.ClearButton([msg, chatbot])
|
118 |
+
|
119 |
+
def user(user_message, history):
|
120 |
+
return gr.update(value="", interactive=False), history + [[user_message, None]]
|
121 |
+
|
122 |
+
def bot(history):
|
123 |
+
user_message = history[-1][0] # get if from most recent history element
|
124 |
+
#bot_message = conversation.run(user_message)
|
125 |
+
response = agent_chain(user_message)
|
126 |
+
bot_message = response['output']
|
127 |
+
history[-1][1] = ""
|
128 |
+
for character in bot_message:
|
129 |
+
history[-1][1] += character
|
130 |
+
#time.sleep(0.05)
|
131 |
+
yield history
|
132 |
+
|
133 |
+
response = msg.submit(user, [msg, chatbot], [msg, chatbot], queue=False).then(
|
134 |
+
bot, chatbot, chatbot
|
135 |
)
|
136 |
+
response.then(lambda: gr.update(interactive=True), None, [msg], queue=False)
|
137 |
|
138 |
+
demo.queue()
|
139 |
+
demo.launch()
|