|
import os |
|
import gradio as gr |
|
import qdrant_client |
|
from llama_index.core import Settings, VectorStoreIndex, StorageContext |
|
from llama_index.vector_stores.qdrant import QdrantVectorStore |
|
from llama_index.embeddings.fastembed import FastEmbedEmbedding |
|
from llama_index.llms.gemini import Gemini |
|
from llama_index.core.memory import ChatMemoryBuffer |
|
from llama_index.readers.web import FireCrawlWebReader |
|
import dotenv |
|
import time |
|
|
|
dotenv.load_dotenv() |
|
|
|
|
|
index = None |
|
chat_engine = None |
|
collection_name = "" |
|
|
|
def embed_setup(): |
|
Settings.embed_model = FastEmbedEmbedding(model_name="BAAI/bge-small-en-v1.5") |
|
Settings.llm = Gemini(temperature=0.1, model_name="models/gemini-pro") |
|
|
|
def qdrant_setup(): |
|
client = qdrant_client.QdrantClient( |
|
os.getenv("QDRANT_URL"), |
|
api_key=os.getenv("QDRANT_API_KEY"), |
|
) |
|
return client |
|
|
|
def ingest_documents(url): |
|
firecrawl_reader = FireCrawlWebReader( |
|
api_key=os.getenv("FIRECRAWL_API_KEY"), |
|
mode="scrape", |
|
) |
|
documents = firecrawl_reader.load_data(url=url) |
|
return documents |
|
|
|
def setup_query_engine(url, coll_name): |
|
global index, chat_engine, collection_name |
|
collection_name = coll_name |
|
|
|
embed_setup() |
|
client = qdrant_setup() |
|
vector_store = QdrantVectorStore(client=client, collection_name=collection_name) |
|
storage_context = StorageContext.from_defaults(vector_store=vector_store) |
|
|
|
if url: |
|
documents = ingest_documents(url) |
|
index = VectorStoreIndex.from_documents(documents, vector_store=vector_store, storage_context=storage_context) |
|
else: |
|
index = VectorStoreIndex.from_vector_store(vector_store=vector_store, storage_context=storage_context) |
|
|
|
memory = ChatMemoryBuffer.from_defaults(token_limit=4000) |
|
chat_engine = index.as_chat_engine( |
|
chat_mode="context", |
|
memory=memory, |
|
system_prompt=( |
|
"""You are an AI assistant for developers, specializing in technical documentation. Your task is to provide accurate, concise, and helpful responses based on the given documentation context. |
|
Context information is below: |
|
{context_str} |
|
Always answer based on the information in the context and general knowledge and be precise |
|
Given this context, please respond to the following user query: |
|
{query_str} |
|
Your response should: |
|
Directly address the query using information from the context |
|
Include relevant code examples or direct quotes if applicable |
|
Mention specific sections or pages of the documentation |
|
Highlight any best practices or potential pitfalls related to the query |
|
After your response, suggest 3 follow-up questions based on the context that the user might find helpful for deeper understanding. |
|
ALWAYS SUGGEST FOLLOW UP QUESTIONS |
|
Your response:""" |
|
), |
|
) |
|
return "Query engine setup completed successfully!" |
|
|
|
def query_documentation(query): |
|
global chat_engine |
|
if not chat_engine: |
|
return "Please set up the query engine first." |
|
|
|
try: |
|
response = chat_engine.chat(query) |
|
return str(response.response) |
|
except Exception as e: |
|
error_message = f"An error occurred: {str(e)}" |
|
time.sleep(120) |
|
try: |
|
response = chat_engine.chat(query) |
|
return str(response.response) |
|
except Exception as e: |
|
return f"Retry failed. Error: {str(e)}" |
|
|
|
|
|
with gr.Blocks() as app: |
|
gr.Markdown("# Talk to Software Documentation") |
|
|
|
with gr.Tab("Setup"): |
|
url_input = gr.Textbox(label="Enter URL to crawl and ingest documents (optional)") |
|
collection_input = gr.Textbox(label="Enter collection name for vector store (compulsory)") |
|
setup_button = gr.Button("Setup Query Engine") |
|
setup_output = gr.Textbox(label="Setup Output") |
|
|
|
setup_button.click(setup_query_engine, inputs=[url_input, collection_input], outputs=setup_output) |
|
|
|
with gr.Tab("Chat"): |
|
chatbot = gr.Chatbot() |
|
msg = gr.Textbox(label="Enter your query") |
|
clear = gr.Button("Clear") |
|
|
|
def user(user_message, history): |
|
return "", history + [[user_message, None]] |
|
|
|
def bot(history): |
|
user_message = history[-1][0] |
|
bot_message = query_documentation(user_message) |
|
history[-1][1] = bot_message |
|
return history |
|
|
|
msg.submit(user, [msg, chatbot], [msg, chatbot], queue=False).then( |
|
bot, chatbot, chatbot |
|
) |
|
clear.click(lambda: None, None, chatbot, queue=False) |
|
|
|
if __name__ == "__main__": |
|
app.launch() |