Spaces:
Running
Running
File size: 11,190 Bytes
8ef6cb8 bb77773 8ef6cb8 bb77773 8ef6cb8 bb77773 7463824 a6ab84c bb77773 a6ab84c bb77773 a6ab84c bb77773 3e21c23 a6ab84c 8ef6cb8 7463824 bb77773 8ef6cb8 a6ab84c 7463824 8ef6cb8 bb77773 8ef6cb8 bb77773 8ef6cb8 a6ab84c 8ef6cb8 a6ab84c bb77773 a6ab84c bb77773 8ef6cb8 a6ab84c bb77773 a6ab84c bb77773 7463824 bb77773 a6ab84c 90dc0e0 a6ab84c bb77773 a6ab84c 7463824 912b2d3 a6ab84c 0d8557a 7463824 a6ab84c bb77773 a6ab84c bb77773 a6ab84c bb77773 a6ab84c 912b2d3 a6ab84c bb77773 a6ab84c 912b2d3 a6ab84c 912b2d3 a6ab84c 912b2d3 a6ab84c 912b2d3 bb77773 a6ab84c 8ef6cb8 a6ab84c |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 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 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 |
from datetime import datetime
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_parse import LlamaParse
from llama_index.llms.huggingface_api import HuggingFaceInferenceAPI
import os
from dotenv import load_dotenv
import gradio as gr
import base64
# Load environment variables
load_dotenv()
llm_models = [
"mistralai/Mixtral-8x7B-Instruct-v0.1",
"meta-llama/Meta-Llama-3-8B-Instruct",
"mistralai/Mistral-7B-Instruct-v0.2",
"tiiuae/falcon-7b-instruct",
]
embed_models = [
"BAAI/bge-small-en-v1.5", # 33.4M
"NeuML/pubmedbert-base-embeddings",
"BAAI/llm-embedder", # 109M
"BAAI/bge-large-en" # 335M
]
# Global variable for selected model
selected_llm_model_name = llm_models[0] # Default to the first model in the list
selected_embed_model_name = embed_models[0] # Default to the first model in the list
vector_index = None
# Initialize the parser
parser = LlamaParse(api_key=os.getenv("LLAMA_INDEX_API"), result_type='markdown')
# Define file extractor with various common extensions
file_extractor = {
'.pdf': parser, # PDF documents
'.docx': parser, # Microsoft Word documents
'.doc': parser, # Older Microsoft Word documents
'.txt': parser, # Plain text files
'.csv': parser, # Comma-separated values files
'.xlsx': parser, # Microsoft Excel files
'.pptx': parser, # Microsoft PowerPoint files
'.html': parser, # HTML files
'.jpg': parser, # JPEG images
'.jpeg': parser, # JPEG images
'.png': parser, # PNG images
'.webp': parser, # WebP images
'.svg': parser, # SVG files
}
# Markdown content definitions
description = """
## Welcome to DocBot ππ€
DocBot is an intelligent document analysis tool that can help you extract insights from various document formats including:
- PDF documents
- Word documents (.docx, .doc)
- Text files
- CSV files
- Excel files
- PowerPoint presentations
- HTML files
- Images with text (JPG, PNG, WebP, SVG)
Simply upload your document, select your preferred embedding model and LLM, then start asking questions!
"""
guide = """
### How to Use DocBot:
1. **Upload Document**: Choose any supported file format
2. **Select Embedding Model**: Choose from available embedding models (BAAI/bge-small-en-v1.5 is recommended for most cases)
3. **Submit**: Click submit to process your document
4. **Select LLM**: Choose your preferred language model
5. **Ask Questions**: Start chatting with your document!
### Tips:
- Smaller embedding models (like bge-small-en-v1.5) are faster but may be less accurate
- Larger models provide better understanding but take more time
- Be specific in your questions for better results
"""
footer = """
<div style="text-align: center; margin-top: 20px; padding: 20px; border-top: 1px solid #ddd;">
<p>Built with β€οΈ using LlamaIndex and Gradio</p>
<div style="display: flex; justify-content: center; gap: 20px; margin-top: 10px;">
<a href="https://github.com" target="_blank">
<img src="data:image/png;base64,{0}" alt="GitHub" style="width: 24px; height: 24px;">
</a>
<a href="https://linkedin.com" target="_blank">
<img src="data:image/png;base64,{1}" alt="LinkedIn" style="width: 24px; height: 24px;">
</a>
<a href="https://your-website.com" target="_blank">
<img src="data:image/png;base64,{2}" alt="Website" style="width: 24px; height: 24px;">
</a>
</div>
</div>
"""
# File processing function
def load_files(file_path: str, embed_model_name: str):
try:
if not file_path:
return "Please select a file first."
if not embed_model_name:
return "Please select an embedding model."
global vector_index
document = SimpleDirectoryReader(input_files=[file_path], file_extractor=file_extractor).load_data()
embed_model = HuggingFaceEmbedding(model_name=embed_model_name)
vector_index = VectorStoreIndex.from_documents(document, embed_model=embed_model)
print(f"Parsing done for {file_path}")
filename = os.path.basename(file_path)
return f"β
Ready to answer questions about: {filename}"
except Exception as e:
return f"β An error occurred: {str(e)}"
# Function to handle the selected model from dropdown
def set_llm_model(selected_model):
global selected_llm_model_name
if selected_model:
selected_llm_model_name = selected_model
return f"LLM set to: {selected_model}"
# Respond function that uses the globally set selected model
def respond(message, history):
try:
if not vector_index:
return "Please upload and process a document first."
if not message.strip():
return "Please enter a question."
# Initialize the LLM with the selected model
llm = HuggingFaceInferenceAPI(
model_name=selected_llm_model_name,
contextWindow=8192,
maxTokens=1024,
temperature=0.3,
topP=0.9,
frequencyPenalty=0.5,
presencePenalty=0.5,
token=os.getenv("TOKEN")
)
# Set up the query engine with the selected LLM
query_engine = vector_index.as_query_engine(llm=llm)
bot_message = query_engine.query(message)
print(f"\n{datetime.now()}:{selected_llm_model_name}:: {message} --> {str(bot_message)}\n")
return f"**{selected_llm_model_name}:**\n\n{str(bot_message)}"
except Exception as e:
return f"β An error occurred: {str(e)}"
def encode_image_safe(image_path):
"""Safely encode image, return empty string if file doesn't exist"""
try:
if os.path.exists(image_path):
with open(image_path, "rb") as image_file:
return base64.b64encode(image_file.read()).decode('utf-8')
except Exception:
pass
return ""
# Clear function for file processing components
def clear_file_components():
return None, embed_models[0], ""
# Encode the images (with fallback for missing images)
github_logo_encoded = encode_image_safe("Images/github-logo.png")
linkedin_logo_encoded = encode_image_safe("Images/linkedin-logo.png")
website_logo_encoded = encode_image_safe("Images/ai-logo.png")
# UI Setup
with gr.Blocks(
theme=gr.themes.Soft(),
css='footer {visibility: hidden}',
title="DocBot - Document Analysis Assistant"
) as demo:
gr.Markdown("# DocBot ππ€")
gr.Markdown("*Intelligent Document Analysis Assistant*")
with gr.Tabs():
with gr.TabItem("π Introduction"):
gr.Markdown(description)
with gr.TabItem("π€ DocBot"):
with gr.Accordion("π Quick Start Guide", open=False):
gr.Markdown(guide)
with gr.Row():
with gr.Column(scale=1):
with gr.Group():
gr.Markdown("### Document Processing")
file_input = gr.File(
file_count="single",
type='filepath',
label="Step 1: Upload Document",
file_types=['.pdf', '.docx', '.doc', '.txt', '.csv', '.xlsx', '.pptx', '.html', '.jpg', '.jpeg', '.png', '.webp', '.svg']
)
embed_model_dropdown = gr.Dropdown(
choices=embed_models,
label="Step 2: Select Embedding Model",
interactive=True,
value=embed_models[0]
)
with gr.Row():
btn = gr.Button("π Process Document", variant='primary', size="lg")
clear_btn = gr.Button("ποΈ Clear", size="lg")
output = gr.Textbox(
label='Processing Status',
interactive=False,
placeholder="Upload a document and click 'Process Document' to begin..."
)
with gr.Group():
gr.Markdown("### Model Selection")
llm_model_dropdown = gr.Dropdown(
choices=llm_models,
label="Step 3: Select Language Model",
interactive=True,
value=llm_models[0]
)
llm_status = gr.Textbox(
label="Selected Model",
interactive=False,
value=f"LLM set to: {llm_models[0]}"
)
with gr.Column(scale=2):
gr.Markdown("### Chat with Your Document")
chatbot = gr.Chatbot(
height=600,
placeholder="Process a document first, then start asking questions!",
show_label=False
)
msg = gr.Textbox(
placeholder="Step 4: Ask questions about your document...",
container=False,
scale=7
)
with gr.Row():
submit_btn = gr.Button("Send", variant="primary")
clear_chat_btn = gr.Button("Clear Chat")
# Add footer if images exist
if any([github_logo_encoded, linkedin_logo_encoded, website_logo_encoded]):
gr.HTML(footer.format(github_logo_encoded, linkedin_logo_encoded, website_logo_encoded))
# Set up event handlers
def chat_respond(message, history):
if not message.strip():
return history, ""
response = respond(message, history)
history.append([message, response])
return history, ""
def clear_chat():
return [], ""
# Event bindings
llm_model_dropdown.change(
fn=set_llm_model,
inputs=[llm_model_dropdown],
outputs=[llm_status]
)
btn.click(
fn=load_files,
inputs=[file_input, embed_model_dropdown],
outputs=[output]
)
submit_btn.click(
fn=chat_respond,
inputs=[msg, chatbot],
outputs=[chatbot, msg]
)
msg.submit(
fn=chat_respond,
inputs=[msg, chatbot],
outputs=[chatbot, msg]
)
clear_btn.click(
fn=clear_file_components,
outputs=[file_input, embed_model_dropdown, output]
)
clear_chat_btn.click(
fn=clear_chat,
outputs=[chatbot, msg]
)
# Launch the demo
if __name__ == "__main__":
demo.launch(
share=True,
server_name="0.0.0.0",
server_port=7860,
show_error=True
) |