Spaces:
Sleeping
Sleeping
Upload app.py
Browse files
app.py
ADDED
@@ -0,0 +1,163 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
## Setup
|
3 |
+
# Import the necessary Libraries
|
4 |
+
import os
|
5 |
+
import uuid
|
6 |
+
import json
|
7 |
+
import gradio as gr
|
8 |
+
|
9 |
+
from openai import OpenAI
|
10 |
+
from langchain_community.embeddings.sentence_transformer import SentenceTransformerEmbeddings
|
11 |
+
from langchain_community.vectorstores import Chroma
|
12 |
+
from huggingface_hub import CommitScheduler
|
13 |
+
from pathlib import Path
|
14 |
+
|
15 |
+
# Create Client
|
16 |
+
client = OpenAI(
|
17 |
+
api_key="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"
|
18 |
+
)
|
19 |
+
|
20 |
+
# Define the embedding model and the vectorstore
|
21 |
+
embedding_model = SentenceTransformerEmbeddings(model_name='gpt=thenlper/gte-small')
|
22 |
+
|
23 |
+
# Load the persisted vectorDB
|
24 |
+
collection_name = '10k_embeddings'
|
25 |
+
|
26 |
+
tenkdb = Chroma(
|
27 |
+
collection_name="10k_embeddings",
|
28 |
+
persist_directory=persisted_vectordb_location,
|
29 |
+
embedding_function=embedding_model
|
30 |
+
)
|
31 |
+
|
32 |
+
# Prepare the logging functionality
|
33 |
+
log_file = Path("logs/") / f"data_{uuid.uuid4()}.json"
|
34 |
+
log_folder = log_file.parent
|
35 |
+
|
36 |
+
scheduler = CommitScheduler(
|
37 |
+
repo_id="10k_report_logs",
|
38 |
+
repo_type="dataset",
|
39 |
+
folder_path=log_folder,
|
40 |
+
path_in_repo="data",
|
41 |
+
every=2
|
42 |
+
)
|
43 |
+
|
44 |
+
# Define the Q&A system message
|
45 |
+
qna_system_message = """
|
46 |
+
You are a financial analyst tasked to research 10K reports from major cloud and AI platforms such as Amazon AWS, Google Cloud, Microsoft Azure, Meta AI, and IBM Watson to determine the most effective platform for this application.
|
47 |
+
|
48 |
+
User input will include the necessary context for you to answer their questions. This context will begin with the token: ###Context.
|
49 |
+
The context contains references to specific portions of documents relevant to the user's query, along with source links.
|
50 |
+
The source for a context will begin with the token ###Source
|
51 |
+
|
52 |
+
When crafting your response:
|
53 |
+
1. Select only context relevant to answer the question.
|
54 |
+
2. Include the source links in your response.
|
55 |
+
3. User questions will begin with the token: ###Question.
|
56 |
+
4. If the question is irrelevant to 10K reports respond with - "I am an assistant for cloud 10k reports. I can only help you with questions related to cloud 10k reports"
|
57 |
+
|
58 |
+
Please adhere to the following guidelines:
|
59 |
+
- Your response should only be about the question asked and nothing else.
|
60 |
+
- Answer only using the context provided.
|
61 |
+
- Do not mention anything about the context in your final answer.
|
62 |
+
- If the answer is not found in the context, it is very very important for you to respond with "I don't know. Please check the 10k docs "
|
63 |
+
- Always quote the source when you use the context. Cite the relevant source at the end of your response under the section - Source:
|
64 |
+
- Do not make up sources. Use the links provided in the sources section of the context and nothing else. You are prohibited from providing other links/sources.
|
65 |
+
|
66 |
+
Here is an example of how to structure your response:
|
67 |
+
|
68 |
+
Answer:
|
69 |
+
[Answer]
|
70 |
+
|
71 |
+
Source:
|
72 |
+
[Source]
|
73 |
+
"""
|
74 |
+
|
75 |
+
# Define the user message template
|
76 |
+
qna_user_message_template = """
|
77 |
+
###Context
|
78 |
+
Here are some documents and their source links that are relevant to the question mentioned below.
|
79 |
+
{context}
|
80 |
+
|
81 |
+
###Question
|
82 |
+
{question}
|
83 |
+
"""
|
84 |
+
|
85 |
+
# Define the predict function that runs when 'Submit' is clicked or when a API request is made
|
86 |
+
def predict(user_input,company):
|
87 |
+
|
88 |
+
filter = "dataset/"+company+"-10-k-2023.pdf"
|
89 |
+
relevant_document_chunks = vectorstore_persisted.similarity_search(user_input, k=5, filter={"source":filter})
|
90 |
+
|
91 |
+
# Create context_for_query
|
92 |
+
context_list = [d.page_content + "\n ###Source: " + d.metadata['source'] + "\n\n " for d in relevant_document_chunks]
|
93 |
+
|
94 |
+
context_for_query = ". ".join(context_list)
|
95 |
+
|
96 |
+
# Create messages
|
97 |
+
prompt = [
|
98 |
+
{'role':'system', 'content': qna_system_message},
|
99 |
+
{'role': 'user', 'content': qna_user_message_template.format(
|
100 |
+
context=context_for_query,
|
101 |
+
question=user_input
|
102 |
+
)
|
103 |
+
}
|
104 |
+
]
|
105 |
+
|
106 |
+
# Get response from the LLM
|
107 |
+
try:
|
108 |
+
response = client.chat.completions.create(
|
109 |
+
model=model_name,
|
110 |
+
messages=prompt,
|
111 |
+
temperature=0
|
112 |
+
)
|
113 |
+
|
114 |
+
prediction = response.choices[0].message.content.strip()
|
115 |
+
except Exception as e:
|
116 |
+
prediction = f'Sorry, I encountered the following error: \n {e}'
|
117 |
+
|
118 |
+
# While the prediction is made, log both the inputs and outputs to a local log file
|
119 |
+
# While writing to the log file, ensure that the commit scheduler is locked to avoid parallel
|
120 |
+
# access
|
121 |
+
|
122 |
+
with scheduler.lock:
|
123 |
+
with log_file.open("a") as f:
|
124 |
+
f.write(json.dumps(
|
125 |
+
{
|
126 |
+
'user_input': user_input,
|
127 |
+
'retrieved_context': context_for_query,
|
128 |
+
'model_response': prediction
|
129 |
+
}
|
130 |
+
))
|
131 |
+
f.write("\n")
|
132 |
+
|
133 |
+
return prediction
|
134 |
+
|
135 |
+
# Set-up the Gradio UI
|
136 |
+
# Add text box and radio button to the interface
|
137 |
+
# The radio button is used to select the company 10k report in which the context needs to be retrieved.
|
138 |
+
|
139 |
+
textbox = gr.Textbox(placeholder="Enter your query here", lines=6)
|
140 |
+
company = gr.Radio(
|
141 |
+
['AWS','Google','Microsoft','Meta','IBM'],
|
142 |
+
label='Company'
|
143 |
+
)
|
144 |
+
|
145 |
+
# Create the interface
|
146 |
+
demo = gr.Interface(
|
147 |
+
inputs=textbox, company, fn=predict, outputs="text",
|
148 |
+
title="Cloud 10-K statements",
|
149 |
+
description="This web API presents an interface to ask questions on contents of various cloud provider 10-K reports for 2023",
|
150 |
+
article="Note that questions that are not relevant to top cloud provider 10-K reports will not be answered.",
|
151 |
+
examples=[["What was the total revenue of the company in 2023?", "$ 81.46 Billion"],
|
152 |
+
["Summarize the Management Discussion and Analysis section of the 2023 report in 50 words.", ""],
|
153 |
+
["What was the company's debt level in 2023?", ""],
|
154 |
+
["Identify 5 key risks identified in the 2023 10k report? Respond with bullet point summaries.", ""]
|
155 |
+
],
|
156 |
+
concurrency_limit=16
|
157 |
+
)
|
158 |
+
|
159 |
+
# For the inputs parameter of Interface provide [textbox,company]
|
160 |
+
|
161 |
+
|
162 |
+
demo.queue()
|
163 |
+
demo.launch()
|