File size: 5,373 Bytes
b676995 5040539 b676995 5040539 b676995 add7f0f 5040539 add7f0f 5040539 1ef3b0b 5040539 b676995 5040539 b676995 5040539 b676995 5040539 b676995 5040539 b676995 5040539 b676995 3ef1980 b676995 5040539 b676995 5040539 b676995 1234b00 b676995 5040539 1234b00 645b0e8 1234b00 645b0e8 b676995 1234b00 645b0e8 1234b00 b676995 1234b00 645b0e8 76b62e6 645b0e8 | 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 | import os
import streamlit as st
import logging
from langchain_groq import ChatGroq
from langchain_community.tools import ArxivQueryRun, WikipediaQueryRun, DuckDuckGoSearchRun
from langchain_community.utilities import ArxivAPIWrapper, WikipediaAPIWrapper
from langchain import hub
from langchain.agents import create_openai_tools_agent, AgentExecutor
from langchain.prompts import PromptTemplate
from langchain_community.vectorstores import FAISS
from langchain_huggingface import HuggingFaceEmbeddings
from langchain.tools import Tool
from pydantic import BaseModel, Field
from typing import List, Dict
# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logging.info("Streamlit app started")
# Load the API key
groq_api_key = "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" #os.getenv("GROQ_API_KEY")
if not groq_api_key:
logging.error("GROQ API key is missing!")
# Define a query condensing template
condense_prompt_template = PromptTemplate(
input_variables=["original_question", "conversation_history"],
template="""
Given the conversation history below, condense the user's query into a clear and specific question.
Conversation History:
{conversation_history}
Original Question:
{original_question}
Condensed Question:"""
)
def condense_query(llm_model, original_question, conversation_history):
prompt = condense_prompt_template.format(
original_question=original_question,
conversation_history=conversation_history
)
resp = llm_model.predict(prompt)
return resp.strip()
# Initialize HuggingFace embeddings and FAISS vectorstore
embeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")
vector_db = FAISS.load_local("faiss_index", embeddings, allow_dangerous_deserialization=True)
retriever_tool = vector_db.as_retriever()
# Define input/output models for OpenAI function-calling compliance
class RetrieveDocumentsInput(BaseModel):
query: str = Field(..., description="Query to retrieve relevant documents.")
class RetrieveDocumentsOutput(BaseModel):
documents: List[Dict[str, str]] = Field(..., description="List of retrieved documents, each containing 'content'.")
# Wrapper function for FAISS retriever
def retrieve_documents(query: str) -> List[Dict[str, str]]:
results = retriever_tool.get_relevant_documents(query)
return [{"content": doc.page_content} for doc in results]
# Define the FAISS tool
faiss_tool = Tool(
name="retrieve_documents",
description="Retrieve documents from FAISS vectorstore.",
func=retrieve_documents,
)
# Initialize tools
arxiv_wrapper = ArxivAPIWrapper(top_k_results=1, doc_content_chars_max=250)
arxiv_tool = ArxivQueryRun(api_wrapper=arxiv_wrapper)
wiki_wrapper = WikipediaAPIWrapper(top_k_results=1, doc_content_chars_max=250)
wiki_tool = WikipediaQueryRun(api_wrapper=wiki_wrapper)
search_tool = DuckDuckGoSearchRun(name="Search")
tools = [arxiv_tool, wiki_tool, search_tool, faiss_tool]
# Set up the agent
prompt = hub.pull("hwchase17/openai-functions-agent")
llm = ChatGroq(model="mixtral-8x7b-32768", api_key=groq_api_key, streaming=True)
agent = create_openai_tools_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
# Initialize session state for messages
if 'messages' not in st.session_state:
st.session_state['messages'] = [{"role": "assistant", "content": "How can I help you?"}]
# Display chat messages
for msg in st.session_state['messages']:
st.chat_message(msg["role"]).write(msg["content"])
# Extract conversation history
conversation_history = "\n".join(
[f"{msg['role']}: {msg['content']}" for msg in st.session_state['messages']]
)
# CSS for input box at bottom of screen
st.markdown("""
<style>
.fixed-bottom-input-container {
position: fixed;
bottom: 0;
width: 100%;
background-color: white;
padding: 10px 0;
border-top: 1px solid #ddd;
}
.fixed-bottom-input {
width: 100%;
padding: 10px;
font-size: 16px;
}
</style>
""", unsafe_allow_html=True)
# Chat input and processing
user_input = st.text_input("Type your message here...", key="user_input", label_visibility="collapsed")
# If there's input, process it
if user_input:
condensed_question = condense_query(llm, user_input, conversation_history)
# Placeholder for streaming the assistant's response
response_placeholder = st.empty()
response_text = ""
# Stream response tokens
for token in agent_executor.stream({"input": condensed_question}):
# Ensure the token contains the "output" key
if "output" in token:
response_text += token["output"]
response_placeholder.write(response_text)
else:
logging.warning("Received token without 'output' key: %s", token)
# Continue with the chat history and message updates
st.session_state.messages.append({"role": "user", "content": user_input})
st.session_state.messages.append({"role": "assistant", "content": response_text})
# Display the user input and response
st.chat_message("user").write(user_input)
st.chat_message("assistant").write(response_text)
# Reset the input box content
user_input = ""
|