Spaces:
Sleeping
Sleeping
Commit
·
c66a864
1
Parent(s):
5ed51c5
Upload 2 files
Browse files- arthur_vectorstore.pkl +3 -0
- launch_ask_arthur_gradio.py +208 -0
arthur_vectorstore.pkl
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:f48e27fbb868a6f6e54599797183284470462c53a47d5c5efdddcee7378bda8f
|
3 |
+
size 6836487
|
launch_ask_arthur_gradio.py
ADDED
@@ -0,0 +1,208 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import argparse
|
2 |
+
import gradio as gr
|
3 |
+
import os
|
4 |
+
import pandas as pd
|
5 |
+
import pickle
|
6 |
+
from typing import List
|
7 |
+
|
8 |
+
from langchain.llms import OpenAIChat
|
9 |
+
from langchain.prompts import PromptTemplate
|
10 |
+
from langchain.chains.question_answering import load_qa_chain
|
11 |
+
from langchain.chains import LLMChain, ChatVectorDBChain
|
12 |
+
from langchain.callbacks.base import CallbackManager
|
13 |
+
from langchain.chains.chat_vector_db.prompts import CONDENSE_QUESTION_PROMPT as SYNTHESIS_PROMPT
|
14 |
+
|
15 |
+
|
16 |
+
response_prompt_template = """You are an AI assistant for the machine learning monitoring startup Arthur. You are
|
17 |
+
given the following extracted parts of a long document and a question. If the question
|
18 |
+
includes a request for code, provide a code block directly from the documentation. If you don't know the answer, just
|
19 |
+
say "Hmm, I'm not sure." Don't try to make up an answer. If the question is not about Arthur, politely inform them that
|
20 |
+
you are tuned to only answer questions about Arthur.
|
21 |
+
|
22 |
+
=========
|
23 |
+
Example 1:
|
24 |
+
|
25 |
+
Question: What data do I need to send to Arthur?
|
26 |
+
=========
|
27 |
+
**3. What if my data is proprietary? Can I still use Arthur?**
|
28 |
+
|
29 |
+
Yes! Arthur offers on-premises installation for customers with data security requirements. By integrating Arthur
|
30 |
+
into your business's on-premises stack, you can be confident that all security requirements are met while still
|
31 |
+
getting the benefits of the computation and analytics Arthur provides.
|
32 |
+
***
|
33 |
+
|
34 |
+
**4. What if I don’t have ground truth labels for my data? Or what if I will have the ground truth labels in the future,
|
35 |
+
but they are not available yet?**
|
36 |
+
|
37 |
+
You don't need ground truth labels to log your model's inferences with Arthur.
|
38 |
+
|
39 |
+
If your ground truth labels become available after your model's inferences, whether seconds later or years later,
|
40 |
+
Arthur can link these new ground truth values to your model's past predictions, linking the new values by ID to
|
41 |
+
their corresponding inferences already in the Arthur system.
|
42 |
+
|
43 |
+
In the meantime, Arthur’s data drift metrics can offer leading indicators of model underperformance to keep you
|
44 |
+
covered if your ground truth labels are delayed or never become available.
|
45 |
+
***
|
46 |
+
=========
|
47 |
+
Answer in Markdown:
|
48 |
+
The data you need to get into Arthur is only the inference data - no ground truth is needed, since it can be uploaded
|
49 |
+
at a later time. Also, if you have proprietary data, you can install Arthur on-premises to keep your own data security protocols.
|
50 |
+
|
51 |
+
=========
|
52 |
+
Now the real question:
|
53 |
+
Question: {question}
|
54 |
+
=========
|
55 |
+
{context}
|
56 |
+
=========
|
57 |
+
Answer in Markdown:"""
|
58 |
+
RESPONSE_PROMPT = PromptTemplate(
|
59 |
+
template=response_prompt_template, input_variables=["context", "question"]
|
60 |
+
)
|
61 |
+
|
62 |
+
|
63 |
+
# load vectorstore of embeddings
|
64 |
+
with open("files/vectorstores/arthur_vectorstore.pkl", "rb") as f:
|
65 |
+
global arthur_vectorstore
|
66 |
+
arthur_vectorstore = pickle.load(f)
|
67 |
+
|
68 |
+
|
69 |
+
def get_langchain_agent(api_key):
|
70 |
+
os.environ["OPENAI_API_KEY"] = api_key
|
71 |
+
|
72 |
+
manager = CallbackManager([])
|
73 |
+
question_manager = CallbackManager([])
|
74 |
+
stream_manager = CallbackManager([])
|
75 |
+
|
76 |
+
question_gen_llm = OpenAIChat(
|
77 |
+
temperature=0,
|
78 |
+
verbose=True,
|
79 |
+
callback_manager=question_manager,
|
80 |
+
)
|
81 |
+
streaming_llm = OpenAIChat(
|
82 |
+
streaming=True,
|
83 |
+
callback_manager=stream_manager,
|
84 |
+
verbose=True,
|
85 |
+
temperature=0,
|
86 |
+
)
|
87 |
+
|
88 |
+
question_generator = LLMChain(
|
89 |
+
llm=question_gen_llm, prompt=SYNTHESIS_PROMPT, callback_manager=manager
|
90 |
+
)
|
91 |
+
chat_response_generator = load_qa_chain(
|
92 |
+
streaming_llm, chain_type="stuff", prompt=RESPONSE_PROMPT, callback_manager=manager
|
93 |
+
)
|
94 |
+
|
95 |
+
agent = ChatVectorDBChain(
|
96 |
+
vectorstore=arthur_vectorstore,
|
97 |
+
combine_docs_chain=chat_response_generator,
|
98 |
+
question_generator=question_generator,
|
99 |
+
callback_manager=manager,
|
100 |
+
return_source_documents=True)
|
101 |
+
|
102 |
+
os.environ["OPENAI_API_KEY"] = ""
|
103 |
+
return agent
|
104 |
+
|
105 |
+
|
106 |
+
def get_source_doc(output):
|
107 |
+
sources = output["source_documents"]
|
108 |
+
assert len(sources) > 0
|
109 |
+
source_document = sources[0]
|
110 |
+
html_filename = source_document.metadata['source']
|
111 |
+
source_doc_link = html_filename.replace('files/', '')
|
112 |
+
source_doc_file = html_filename.replace('files/docs.arthur.ai/', '').replace('.html', '')
|
113 |
+
with open(f"files/arthur-docs-markdown/{source_doc_file}.md.txt", 'r') as f:
|
114 |
+
source_text = f.read()
|
115 |
+
return source_text, source_doc_link
|
116 |
+
|
117 |
+
|
118 |
+
def log_inference(chat_history: List[List[str]], llm_feedback: int) -> None:
|
119 |
+
reference_data = pd.read_csv("files/reference_data.csv", index_col=None)
|
120 |
+
chat_text = []
|
121 |
+
for user_text, bot_text in chat_history:
|
122 |
+
bot_text = bot_text.replace("\n", "").replace("<br>", "")
|
123 |
+
chat_text.append(f"input:<{user_text}>,output:<{bot_text}>,")
|
124 |
+
reference_data.loc[len(reference_data)] = {"chat": "".join(chat_text), "llm_feedback": llm_feedback}
|
125 |
+
reference_data.to_csv("files/reference_data.csv", index=False)
|
126 |
+
|
127 |
+
|
128 |
+
def chat(inp, history, agent):
|
129 |
+
history = history or []
|
130 |
+
result = agent({"question": inp, "chat_history": history})
|
131 |
+
chat_result = result["answer"]
|
132 |
+
source_doc, source_link = get_source_doc(result)
|
133 |
+
response = ""
|
134 |
+
for word in chat_result.split(" "):
|
135 |
+
response += word + " "
|
136 |
+
yield history + [(inp, response)], history + [(inp, response)], source_doc, source_link
|
137 |
+
|
138 |
+
|
139 |
+
def launch_ask_arthur(share=False):
|
140 |
+
with gr.Blocks() as demo:
|
141 |
+
with gr.Row():
|
142 |
+
gr.Markdown("<h1><center>Ask Arthur</center></h1><br><h7><center>"
|
143 |
+
"This is an experimental document-retrieval question-answering system. When you enter a message"
|
144 |
+
" into the chat, 1. we fetch a relevant page from the Arthur documentation (shown on the left) "
|
145 |
+
"and 2. we prompt the Arthur LLM (shown on the right) to answer your question using the page. "
|
146 |
+
"The LLM's answers are entirely unverified, but it can sometimes offer a helpful summary of a "
|
147 |
+
"lot of information, or integrate information from multiple sources for you.</center></h7>")
|
148 |
+
with gr.Column():
|
149 |
+
openai_api_key_textbox = gr.Textbox(
|
150 |
+
placeholder="Paste your OpenAI API key (sk-...)",
|
151 |
+
show_label=False,
|
152 |
+
lines=1,
|
153 |
+
type="password",
|
154 |
+
)
|
155 |
+
submit_api_key_button = gr.Button(value="Register API Key", variant="secondary").style(full_width=False)
|
156 |
+
with gr.Row().style():
|
157 |
+
with gr.Column():
|
158 |
+
chatbot = gr.Chatbot(
|
159 |
+
label="AskArthur chat history")
|
160 |
+
message = gr.Textbox(
|
161 |
+
label="In the AskArthur chat, you can ask follow up questions or ask for clarifications!"
|
162 |
+
"\nReload the demo to change the topic of conversation and refresh the language model.",
|
163 |
+
placeholder="Enter your question here...",
|
164 |
+
lines=1,
|
165 |
+
)
|
166 |
+
submit_message = gr.Button(value="Send", variant="secondary").style(full_width=False)
|
167 |
+
gr.Examples(label="Frequently asked questions about Arthur",
|
168 |
+
examples=[
|
169 |
+
"What default drift metrics does Arthur for deployed models?",
|
170 |
+
"How do I integrate Arthur with my existing ML stack?",
|
171 |
+
"How does Arthur monitor models without ground truth?",
|
172 |
+
"Can you explain the following error message: ",
|
173 |
+
],
|
174 |
+
inputs=message,
|
175 |
+
)
|
176 |
+
# feedback radio button
|
177 |
+
llm_feedback = gr.Radio(
|
178 |
+
["0","1","2"], value="0", label="How useful was this? (0 = bad, 1 = meh, 2 = good)"
|
179 |
+
)
|
180 |
+
submit_feedback_button = gr.Button("Submit feedback")
|
181 |
+
with gr.Column():
|
182 |
+
source_link = gr.Markdown()
|
183 |
+
source_page = gr.Markdown()
|
184 |
+
|
185 |
+
state = gr.State()
|
186 |
+
agent_state = gr.State()
|
187 |
+
submit_api_key_button.click(
|
188 |
+
get_langchain_agent,
|
189 |
+
inputs=[openai_api_key_textbox],
|
190 |
+
outputs=[agent_state],
|
191 |
+
)
|
192 |
+
submit_message.click(chat, inputs=[message, state, agent_state], outputs=[chatbot, state, source_page, source_link])
|
193 |
+
message.submit(chat, inputs=[message, state, agent_state], outputs=[chatbot, state, source_page, source_link])
|
194 |
+
|
195 |
+
|
196 |
+
submit_feedback_button.click(
|
197 |
+
log_inference,
|
198 |
+
[chatbot, llm_feedback],
|
199 |
+
)
|
200 |
+
|
201 |
+
demo.queue().launch(share=share)
|
202 |
+
|
203 |
+
|
204 |
+
if __name__ == "__main__":
|
205 |
+
parser = argparse.ArgumentParser()
|
206 |
+
parser.add_argument("--share", type=bool, required=False)
|
207 |
+
args = parser.parse_args()
|
208 |
+
launch_ask_arthur(share=args.share)
|