Skip to content

Commit

Permalink
Update .gitignore
Browse files Browse the repository at this point in the history
  • Loading branch information
ashpreetbedi committed Apr 11, 2024
1 parent 11bb1f8 commit 0208d79
Show file tree
Hide file tree
Showing 11 changed files with 181 additions and 198 deletions.
164 changes: 85 additions & 79 deletions cookbook/integrations/singlestore/auto_rag/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,80 +3,64 @@
import streamlit as st
from phi.assistant import Assistant
from phi.document import Document
from phi.document.reader.pdf import PDFReader
from phi.document.reader.website import WebsiteReader
from phi.tools.streamlit.components import (
check_password,
reload_button_sidebar,
get_username_sidebar,
)

from assistant import get_local_rag_assistant # Adjust the import statement as needed
from logging import getLogger
from phi.tools.streamlit.components import reload_button_sidebar
from phi.utils.log import logger

logger = getLogger(__name__)
from assistant import get_assistant # type: ignore

st.set_page_config(
page_title="Local RAG with Web Scraping \n Using SingleStore as a backend databse",
page_title="Autonomous RAG",
page_icon=":orange_heart:",
)
st.title("Local RAG with Web Scraping")
st.title("Autonomous RAG with SingleStore")
st.markdown("##### :orange_heart: Built using [phidata](https://github.com/phidatahq/phidata)")


def restart_assistant():
st.session_state["web_assistant"] = None
st.session_state["web_assistant_run_id"] = None
st.session_state["assistant"] = None
st.session_state["assistant_run_id"] = None
st.session_state["url_scrape_key"] += 1
st.session_state["file_uploader_key"] += 1
st.rerun()


def main() -> None:
# Get username
username = get_username_sidebar()
if username:
st.sidebar.info(f":technologist: User: {username}")
else:
st.write(":technologist: Please enter a username")
return

# Get model
local_rag_model = st.sidebar.selectbox("Select Model", options=["GPT-4", "Hermes2", "Claude"])
# Set assistant_type in session state
if "local_rag_model" not in st.session_state:
st.session_state["local_rag_model"] = local_rag_model
# Restart the assistant if assistant_type has changed
elif st.session_state["local_rag_model"] != local_rag_model:
st.session_state["local_rag_model"] = local_rag_model
# Get LLM Model
llm = st.sidebar.selectbox("Select Model", options=["GPT-4", "GPT-3.5", "Hermes2"])
# Set llm in session state
if "llm" not in st.session_state:
st.session_state["llm"] = llm
# Restart the assistant if llm changes
elif st.session_state["llm"] != llm:
st.session_state["llm"] = llm
restart_assistant()

# Get the assistant
web_assistant: Assistant
if "web_assistant" not in st.session_state or st.session_state["web_assistant"] is None:
logger.info("---*--- Creating Web Assistant ---*---")
web_assistant = get_local_rag_assistant(
model=local_rag_model,
user_id=username,
debug_mode=True,
)
st.session_state["web_assistant"] = web_assistant
assistant: Assistant
if "assistant" not in st.session_state or st.session_state["assistant"] is None:
logger.info("---*--- Creating Assistant ---*---")
assistant = get_assistant(model=llm)
st.session_state["assistant"] = assistant
else:
web_assistant = st.session_state["web_assistant"]
assistant = st.session_state["assistant"]

# Create assistant run (i.e. log to database) and save run_id in session state
try:
st.session_state["web_assistant_run_id"] = web_assistant.create_run()
st.session_state["assistant_run_id"] = assistant.create_run()
except Exception:
st.warning("Could not create assistant, is the database running?")
return

# Load existing messages
assistant_chat_history = web_assistant.memory.get_chat_history()
assistant_chat_history = assistant.memory.get_chat_history()
if len(assistant_chat_history) > 0:
logger.debug("Loading chat history")
st.session_state["messages"] = assistant_chat_history
else:
logger.debug("No chat history found")
st.session_state["messages"] = [{"role": "web_assistant", "content": "Ask me anything..."}]
st.session_state["messages"] = [{"role": "assistant", "content": "Ask me anything..."}]

# Prompt for user input
if prompt := st.chat_input():
Expand All @@ -93,61 +77,83 @@ def main() -> None:
last_message = st.session_state["messages"][-1]
if last_message.get("role") == "user":
question = last_message["content"]
with st.chat_message("web_assistant"):
with st.chat_message("assistant"):
response = ""
resp_container = st.empty()
for delta in web_assistant.run(question):
for delta in assistant.run(question):
response += delta # type: ignore
resp_container.markdown(response)

st.session_state["messages"].append({"role": "web_assistant", "content": response})

if st.sidebar.button("New Run"):
restart_assistant()

if st.sidebar.button("Auto Rename"):
web_assistant.auto_rename_run()
st.session_state["messages"].append({"role": "assistant", "content": response})

# Upload Web Content
if web_assistant.knowledge_base:
# Load knowledge base
if assistant.knowledge_base:
# -*- Add websites to knowledge base
if "url_scrape_key" not in st.session_state:
st.session_state["url_scrape_key"] = 0

scraped_url = st.sidebar.text_input("Input URL", type="default", key=st.session_state["url_scrape_key"])
append_button = st.sidebar.button("Search URL")
if append_button:
if scraped_url is not None:
alert = st.sidebar.info("Processing URLs...", icon="🧠")
if f"{scraped_url}_scraped" not in st.session_state:
input_url = st.sidebar.text_input(
"Add URL to Knowledge Base", type="default", key=st.session_state["url_scrape_key"]
)
add_url_button = st.sidebar.button("Add URL")
if add_url_button:
if input_url is not None:
alert = st.sidebar.info("Processing URLs...", icon="ℹ️")
if f"{input_url}_scraped" not in st.session_state:
scraper = WebsiteReader()
web_documents: List[Document] = scraper.read(scraped_url)
web_documents: List[Document] = scraper.read(input_url)
if web_documents:
web_assistant.knowledge_base.load_documents(web_documents, upsert=True, skip_existing=True)
assistant.knowledge_base.load_documents(web_documents, upsert=True)
else:
st.sidebar.error("Could not read Website")
st.session_state[f"{scraped_url}_uploaded"] = True
st.sidebar.error("Could not read website")
st.session_state[f"{input_url}_uploaded"] = True
alert.empty()

if web_assistant.storage:
web_assistant_run_ids: List[str] = web_assistant.storage.get_all_run_ids(user_id=username)
new_web_assistant_run_id = st.sidebar.selectbox("Run ID", options=web_assistant_run_ids)
if st.session_state["web_assistant_run_id"] != new_web_assistant_run_id:
logger.info(f"---*--- Loading run: {new_web_assistant_run_id} ---*---")
st.session_state["web_assistant"] = get_local_rag_assistant(
model=local_rag_model,
user_id=username,
run_id=new_web_assistant_run_id,
debug_mode=True,
)
# Add PDFs to knowledge base
if "file_uploader_key" not in st.session_state:
st.session_state["file_uploader_key"] = 100

uploaded_file = st.sidebar.file_uploader(
"Add a PDF :page_facing_up:", type="pdf", key=st.session_state["file_uploader_key"]
)
if uploaded_file is not None:
alert = st.sidebar.info("Processing PDF...", icon="ℹ️")
pdf_name = uploaded_file.name.split(".")[0]
if f"{pdf_name}_uploaded" not in st.session_state:
reader = PDFReader()
pdf_documents: List[Document] = reader.read(uploaded_file)
if pdf_documents:
assistant.knowledge_base.load_documents(documents=pdf_documents, upsert=True)
else:
st.sidebar.error("Could not read PDF")
st.session_state[f"{pdf_name}_uploaded"] = True
alert.empty()
st.sidebar.success(":information_source: If the PDF throws an error, try uploading it again")

if assistant.storage:
assistant_run_ids: List[str] = assistant.storage.get_all_run_ids()
new_assistant_run_id = st.sidebar.selectbox("Run ID", options=assistant_run_ids)
if new_assistant_run_id is not None and st.session_state["assistant_run_id"] != new_assistant_run_id:
logger.info(f"---*--- Loading run: {new_assistant_run_id} ---*---")
st.session_state["assistant"] = get_assistant(model=llm, run_id=new_assistant_run_id)
st.rerun()

web_assistant_run_name = web_assistant.run_name
if web_assistant_run_name:
st.sidebar.write(f":thread: {web_assistant_run_name}")
assistant_run_name = assistant.run_name
if assistant_run_name:
st.sidebar.write(f":thread: {assistant_run_name}")

if st.sidebar.button("New Run"):
restart_assistant()

if st.sidebar.button("Auto Rename"):
assistant.auto_rename_run()

if assistant.knowledge_base:
if st.sidebar.button("Clear Knowledge Base"):
assistant.knowledge_base.clear()

# Show reload button
reload_button_sidebar()


if check_password():
main()
main()
91 changes: 55 additions & 36 deletions cookbook/integrations/singlestore/auto_rag/assistant.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,64 +3,83 @@

from phi.assistant import Assistant
from phi.knowledge import AssistantKnowledge
from phi.llm import LLM
from phi.llm.openai import OpenAIChat
from phi.llm.anthropic import Claude
from phi.llm.ollama import Hermes
from phi.embedder import Embedder
from phi.embedder.openai import OpenAIEmbedder
from phi.embedder.ollama import OllamaEmbedder
from phi.tools.duckduckgo import DuckDuckGo
from phi.storage.assistant.singlestore import S2AssistantStorage
from phi.vectordb.singlestore import S2VectorDb


# Setup SingleStore connection
db_url = f"mysql+pymysql://{getenv("SINGLESTORE_USERNAME")}:{getenv("SINGLESTORE_PASSWORD")}@{getenv("SINGLESTORE_HOST")}:{getenv("SINGLESTORE_PORT")}/{getenv("SINGLESTORE_DATABASE")}?ssl_ca={getenv("SINGLESTORE_SSL_CERT")}&ssl_verify_cert=true"
# -*- SingleStore Configuration -*-
USERNAME = getenv("SINGLESTORE_USERNAME")
PASSWORD = getenv("SINGLESTORE_PASSWORD")
HOST = getenv("SINGLESTORE_HOST")
PORT = getenv("SINGLESTORE_PORT")
DATABASE = getenv("SINGLESTORE_DATABASE")
SSL_CERT = getenv("SINGLESTORE_SSL_CERT")
# -*- SingleStore DB URL
db_url = f"mysql+pymysql://{USERNAME}:{PASSWORD}@{HOST}:{PORT}/{DATABASE}?ssl_ca={SSL_CERT}&ssl_verify_cert=true"

local_assistant_storage = S2AssistantStorage(
table_name="local_rag_assistant",
schema=getenv("SINGLESTORE_DATABASE"),
db_url=db_url,
)

local_assistant_knowledge = AssistantKnowledge(
vector_db=S2VectorDb(
collection="web_documents_singlestore",
schema=getenv("SINGLESTORE_DATABASE"),
db_url=db_url,
# Assuming OllamaEmbedder or a compatible embedder is used for SingleStore
embedder=OllamaEmbedder(model="nomic-embed-text", dimensions=768),
),
num_documents=5,
)


def get_local_rag_assistant(
def get_assistant(
model: str = "GPT-4",
user_id: Optional[str] = None,
run_id: Optional[str] = None,
debug_mode: bool = False,
debug_mode: bool = True,
) -> Assistant:
"""Get a Local URL RAG Assistant with SingleStore backend."""
"""Get a Phidata Assistant with SingleStore backend."""

# Create Assistant Storage
assistant_storage = S2AssistantStorage(table_name="auto_rag_assistant_runs", schema=DATABASE, db_url=db_url)

if model == "GPT-4":
llm = OpenAIChat(model="gpt-4-turbo-preview")
elif model == "Hermes2":
# Create default LLM and Embedder
llm: LLM = OpenAIChat(model="gpt-4-turbo-preview")
embedder: Embedder = OpenAIEmbedder(model="text-embedding-3-small", dimensions=1536)
table_name = "auto_rag_documents_openai"

if model == "Hermes2":
llm = Hermes(model="adrienbrault/nous-hermes2pro:Q8_0")
elif model == "Claude":
llm = Claude(model="claude-3-opus-20240229")
embedder = OllamaEmbedder(model="nomic-embed-text", dimensions=768)
table_name = "auto_rag_documents_nomic"
elif model == "GPT-3.5":
llm = OpenAIChat(model="gpt-3.5-turbo-0125")

# Create Assistant Knowledge
assistant_knowledge = AssistantKnowledge(
vector_db=S2VectorDb(
collection=table_name,
schema=DATABASE,
db_url=db_url,
embedder=embedder,
),
num_documents=5,
)

return Assistant(
name="local_rag_assistant",
name="auto_rag_assistant",
run_id=run_id,
user_id=user_id,
llm=llm,
storage=local_assistant_storage,
knowledge_base=local_assistant_knowledge,
add_chat_history_to_messages=False,
add_references_to_prompt=True,
storage=assistant_storage,
knowledge_base=assistant_knowledge,
add_chat_history_to_messages=True,
num_history_messages=4,
markdown=True,
debug_mode=debug_mode,
description="You are an AI called 'Phi' designed to help users answer questions from a knowledge base.",
assistant_data={"assistant_type": "rag"},
use_tools=True,
description="You are an AI Assistant called 'Phi' designed to help users answer questions. You have access to a knowledge base and can search the web for information if needed.",
instructions=[
"When a user asks a question, always search your knowledge base first using `search_knowledge_base` tool to find relevant information.",
"If you find information relevant to the user's question, provide a clear and concise answer to the user.",
"If you do not find information in your knowledge base, search the web using the `duckduckgo_search` tool and provide a clear and concise answer to the user.",
"Keep your conversation light hearted and fun.",
"Always aim to please the user",
],
show_tool_calls=True,
search_knowledge=True,
read_chat_history=True,
tools=[DuckDuckGo()],
)
3 changes: 2 additions & 1 deletion cookbook/integrations/singlestore/auto_rag/requirements.in
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ pymysql
sqlalchemy
phidata
ollama
anthropic
bs4
duckduckgo-search
Loading

0 comments on commit 0208d79

Please sign in to comment.