From 06a25cdb8f2889c986c931f8119c4f0774951008 Mon Sep 17 00:00:00 2001 From: Ashpreet Bedi Date: Mon, 20 May 2024 01:22:48 -0700 Subject: [PATCH] Personalization --- cookbook/agents/requirements.txt | 2 +- cookbook/examples/auto_rag/requirements.txt | 2 +- cookbook/examples/data_eng/requirements.txt | 2 +- .../{memory => personalization}/README.md | 22 ++--- .../{memory => personalization}/__init__.py | 0 .../{memory => personalization}/app.py | 82 ++++++++++++------- .../{memory => personalization}/assistant.py | 25 ++++-- .../requirements.in | 0 .../requirements.txt | 2 +- cookbook/examples/research/requirements.txt | 2 +- cookbook/examples/sql/requirements.txt | 2 +- .../examples/worldbuilding/requirements.txt | 2 +- .../singlestore/ai_apps/requirements.txt | 2 +- cookbook/llm_os/requirements.txt | 2 +- cookbook/llms/groq/ai_apps/requirements.txt | 2 +- cookbook/llms/groq/auto_rag/requirements.txt | 2 +- .../investment_researcher/requirements.txt | 2 +- .../llms/groq/news_articles/requirements.txt | 2 +- cookbook/llms/groq/rag/requirements.txt | 2 +- cookbook/llms/groq/research/requirements.txt | 2 +- .../llms/groq/video_summary/requirements.txt | 2 +- .../llms/hermes2/auto_rag/requirements.txt | 2 +- cookbook/llms/mistral/rag/requirements.txt | 2 +- .../llms/ollama/auto_rag/requirements.txt | 2 +- cookbook/llms/ollama/rag/requirements.txt | 2 +- cookbook/llms/ollama/tools/requirements.txt | 2 +- .../ollama/video_summary/requirements.txt | 2 +- .../llms/openai/auto_rag/requirements.txt | 2 +- phi/assistant/assistant.py | 19 +++-- phi/memory/assistant.py | 1 + phi/memory/classifier.py | 8 +- phi/memory/manager.py | 14 ++-- 32 files changed, 125 insertions(+), 92 deletions(-) rename cookbook/examples/{memory => personalization}/README.md (57%) rename cookbook/examples/{memory => personalization}/__init__.py (100%) rename cookbook/examples/{memory => personalization}/app.py (60%) rename cookbook/examples/{memory => personalization}/assistant.py (73%) rename cookbook/examples/{memory => personalization}/requirements.in (100%) rename cookbook/examples/{memory => personalization}/requirements.txt (99%) diff --git a/cookbook/agents/requirements.txt b/cookbook/agents/requirements.txt index c2e723c9a..20138d497 100644 --- a/cookbook/agents/requirements.txt +++ b/cookbook/agents/requirements.txt @@ -136,7 +136,7 @@ peewee==3.17.5 # via yfinance pgvector==0.2.5 # via -r cookbook/llm_os/requirements.in -phidata==2.4.8 +phidata==2.4.10 # via -r cookbook/llm_os/requirements.in pillow==10.3.0 # via diff --git a/cookbook/examples/auto_rag/requirements.txt b/cookbook/examples/auto_rag/requirements.txt index ad3685e60..119abeb56 100644 --- a/cookbook/examples/auto_rag/requirements.txt +++ b/cookbook/examples/auto_rag/requirements.txt @@ -107,7 +107,7 @@ pandas==2.2.2 # streamlit pgvector==0.2.5 # via -r cookbook/llms/openai/auto_rag/requirements.in -phidata==2.4.8 +phidata==2.4.10 # via -r cookbook/llms/openai/auto_rag/requirements.in pillow==10.3.0 # via streamlit diff --git a/cookbook/examples/data_eng/requirements.txt b/cookbook/examples/data_eng/requirements.txt index 653eec726..f6b73af0e 100644 --- a/cookbook/examples/data_eng/requirements.txt +++ b/cookbook/examples/data_eng/requirements.txt @@ -86,7 +86,7 @@ pandas==2.2.2 # -r cookbook/examples/data_eng/requirements.in # altair # streamlit -phidata==2.4.8 +phidata==2.4.10 # via -r cookbook/examples/data_eng/requirements.in pillow==10.3.0 # via streamlit diff --git a/cookbook/examples/memory/README.md b/cookbook/examples/personalization/README.md similarity index 57% rename from cookbook/examples/memory/README.md rename to cookbook/examples/personalization/README.md index 49cc9cd27..933a9354d 100644 --- a/cookbook/examples/memory/README.md +++ b/cookbook/examples/personalization/README.md @@ -1,9 +1,8 @@ -# Autonomous RAG with Personalized Memory +# Personalized Memory & Autonomous RAG -This cookbook shows how to do Autonomous retrieval-augmented generation with GPT4. +This cookbook implements Personalized Memory & Autonomous retrieval-augmented generation. -Auto-RAG is just a fancy name for giving the LLM tools like "search_knowledge_base", "read_chat_history", "search_the_web" -and letting it decide how to retrieve the information it needs to answer the question. +i.e. the Assistant will remember details about the user across runs. Similar to how [ChatGPT implements Memory](https://openai.com/index/memory-and-new-controls-for-chatgpt/). > Note: Fork and clone this repository if needed @@ -23,7 +22,7 @@ export OPENAI_API_KEY=*** ### 3. Install libraries ```shell -pip install -r cookbook/examples/auto_rag/requirements.txt +pip install -r cookbook/examples/personalization/requirements.txt ``` ### 4. Run PgVector @@ -50,16 +49,17 @@ docker run -d \ phidata/pgvector:16 ``` -### 5. Run Autonomous RAG App +### 5. Run personalized Autonomous RAG App ```shell -streamlit run cookbook/examples/auto_rag/app.py +streamlit run cookbook/examples/personalization/app.py ``` -- Open [localhost:8501](http://localhost:8501) to view your RAG app. -- Add websites or PDFs and ask question. - -- Example Website: https://techcrunch.com/2024/04/18/meta-releases-llama-3-claims-its-among-the-best-open-models-available/ +- Open [localhost:8501](http://localhost:8501) to view the streamlit app. +- Add to memory: "call me 'your highness'" +- Add to memory: "always respond with a nice greeting and salutation" +- Add to memory: "i like cats so add a cat pun in the response" +- Add a website to the knowledge base: https://techcrunch.com/2024/04/18/meta-releases-llama-3-claims-its-among-the-best-open-models-available/ - Ask questions like: - What did Meta release? - Tell me more about the Llama 3 models? diff --git a/cookbook/examples/memory/__init__.py b/cookbook/examples/personalization/__init__.py similarity index 100% rename from cookbook/examples/memory/__init__.py rename to cookbook/examples/personalization/__init__.py diff --git a/cookbook/examples/memory/app.py b/cookbook/examples/personalization/app.py similarity index 60% rename from cookbook/examples/memory/app.py rename to cookbook/examples/personalization/app.py index 2ca43a846..1c740c379 100644 --- a/cookbook/examples/memory/app.py +++ b/cookbook/examples/personalization/app.py @@ -6,23 +6,24 @@ 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 get_username_sidebar from phi.utils.log import logger -from assistant import get_auto_rag_assistant # type: ignore +from assistant import get_personalized_auto_rag_assistant # type: ignore nest_asyncio.apply() st.set_page_config( - page_title="Autonomous RAG", + page_title="Personalized Memory & Auto RAG", page_icon=":orange_heart:", ) -st.title("Autonomous RAG") +st.title("Personalized Memory & Auto RAG") st.markdown("##### :orange_heart: built using [phidata](https://github.com/phidatahq/phidata)") def restart_assistant(): logger.debug("---*--- Restarting Assistant ---*---") - st.session_state["auto_rag_assistant"] = None - st.session_state["auto_rag_assistant_run_id"] = None + st.session_state["personalized_auto_rag_assistant"] = None + st.session_state["personalized_auto_rag_assistant_run_id"] = None if "url_scrape_key" in st.session_state: st.session_state["url_scrape_key"] += 1 if "file_uploader_key" in st.session_state: @@ -31,8 +32,16 @@ def restart_assistant(): def main() -> None: + # Get username + user_id = get_username_sidebar() + if user_id: + st.sidebar.info(f":technologist: User: {user_id}") + else: + st.write(":technologist: Please enter a username") + return + # Get LLM model - llm_model = st.sidebar.selectbox("Select LLM", options=["gpt-4-turbo", "gpt-3.5-turbo"]) + llm_model = st.sidebar.selectbox("Select LLM", options=["gpt-4o", "gpt-4-turbo"]) # Set assistant_type in session state if "llm_model" not in st.session_state: st.session_state["llm_model"] = llm_model @@ -42,23 +51,26 @@ def main() -> None: restart_assistant() # Get the assistant - auto_rag_assistant: Assistant - if "auto_rag_assistant" not in st.session_state or st.session_state["auto_rag_assistant"] is None: + personalized_auto_rag_assistant: Assistant + if ( + "personalized_auto_rag_assistant" not in st.session_state + or st.session_state["personalized_auto_rag_assistant"] is None + ): logger.info(f"---*--- Creating {llm_model} Assistant ---*---") - auto_rag_assistant = get_auto_rag_assistant(llm_model=llm_model) - st.session_state["auto_rag_assistant"] = auto_rag_assistant + personalized_auto_rag_assistant = get_personalized_auto_rag_assistant(llm_model=llm_model, user_id=user_id) + st.session_state["personalized_auto_rag_assistant"] = personalized_auto_rag_assistant else: - auto_rag_assistant = st.session_state["auto_rag_assistant"] + personalized_auto_rag_assistant = st.session_state["personalized_auto_rag_assistant"] # Create assistant run (i.e. log to database) and save run_id in session state try: - st.session_state["auto_rag_assistant_run_id"] = auto_rag_assistant.create_run() + st.session_state["personalized_auto_rag_assistant_run_id"] = personalized_auto_rag_assistant.create_run() except Exception: st.warning("Could not create assistant, is the database running?") return # Load existing messages - assistant_chat_history = auto_rag_assistant.memory.get_chat_history() + assistant_chat_history = personalized_auto_rag_assistant.memory.get_chat_history() if len(assistant_chat_history) > 0: logger.debug("Loading chat history") st.session_state["messages"] = assistant_chat_history @@ -84,13 +96,13 @@ def main() -> None: with st.chat_message("assistant"): resp_container = st.empty() response = "" - for delta in auto_rag_assistant.run(question): + for delta in personalized_auto_rag_assistant.run(question): response += delta # type: ignore resp_container.markdown(response) st.session_state["messages"].append({"role": "assistant", "content": response}) # Load knowledge base - if auto_rag_assistant.knowledge_base: + if personalized_auto_rag_assistant.knowledge_base: # -*- Add websites to knowledge base if "url_scrape_key" not in st.session_state: st.session_state["url_scrape_key"] = 0 @@ -106,7 +118,7 @@ def main() -> None: scraper = WebsiteReader(max_links=2, max_depth=1) web_documents: List[Document] = scraper.read(input_url) if web_documents: - auto_rag_assistant.knowledge_base.load_documents(web_documents, upsert=True) + personalized_auto_rag_assistant.knowledge_base.load_documents(web_documents, upsert=True) else: st.sidebar.error("Could not read website") st.session_state[f"{input_url}_uploaded"] = True @@ -126,33 +138,43 @@ def main() -> None: reader = PDFReader() auto_rag_documents: List[Document] = reader.read(uploaded_file) if auto_rag_documents: - auto_rag_assistant.knowledge_base.load_documents(auto_rag_documents, upsert=True) + personalized_auto_rag_assistant.knowledge_base.load_documents(auto_rag_documents, upsert=True) else: st.sidebar.error("Could not read PDF") st.session_state[f"{auto_rag_name}_uploaded"] = True alert.empty() - if auto_rag_assistant.knowledge_base and auto_rag_assistant.knowledge_base.vector_db: + if personalized_auto_rag_assistant.knowledge_base and personalized_auto_rag_assistant.knowledge_base.vector_db: if st.sidebar.button("Clear Knowledge Base"): - auto_rag_assistant.knowledge_base.vector_db.clear() + personalized_auto_rag_assistant.knowledge_base.vector_db.clear() st.sidebar.success("Knowledge base cleared") - if auto_rag_assistant.storage: - auto_rag_assistant_run_ids: List[str] = auto_rag_assistant.storage.get_all_run_ids() - new_auto_rag_assistant_run_id = st.sidebar.selectbox("Run ID", options=auto_rag_assistant_run_ids) - if st.session_state["auto_rag_assistant_run_id"] != new_auto_rag_assistant_run_id: - logger.info(f"---*--- Loading {llm_model} run: {new_auto_rag_assistant_run_id} ---*---") - st.session_state["auto_rag_assistant"] = get_auto_rag_assistant( - llm_model=llm_model, run_id=new_auto_rag_assistant_run_id + if personalized_auto_rag_assistant.storage: + personalized_auto_rag_assistant_run_ids: List[str] = personalized_auto_rag_assistant.storage.get_all_run_ids( + user_id=user_id + ) + new_personalized_auto_rag_assistant_run_id = st.sidebar.selectbox( + "Run ID", options=personalized_auto_rag_assistant_run_ids + ) + if st.session_state["personalized_auto_rag_assistant_run_id"] != new_personalized_auto_rag_assistant_run_id: + logger.info(f"---*--- Loading {llm_model} run: {new_personalized_auto_rag_assistant_run_id} ---*---") + st.session_state["personalized_auto_rag_assistant"] = get_personalized_auto_rag_assistant( + llm_model=llm_model, user_id=user_id, run_id=new_personalized_auto_rag_assistant_run_id ) st.rerun() + # Show Assistant memory + if personalized_auto_rag_assistant.memory.memories and len(personalized_auto_rag_assistant.memory.memories) > 0: + logger.info("Loading assistant memory") + with st.status("Assistant Memory", expanded=False, state="complete"): + with st.container(): + memory_container = st.empty() + memory_container.markdown( + "\n".join([f"- {m.memory}" for m in personalized_auto_rag_assistant.memory.memories]) + ) + if st.sidebar.button("New Run"): restart_assistant() - if "embeddings_model_updated" in st.session_state: - st.sidebar.info("Please add documents again as the embeddings model has changed.") - st.session_state["embeddings_model_updated"] = False - main() diff --git a/cookbook/examples/memory/assistant.py b/cookbook/examples/personalization/assistant.py similarity index 73% rename from cookbook/examples/memory/assistant.py rename to cookbook/examples/personalization/assistant.py index 4555ee114..a357759c2 100644 --- a/cookbook/examples/memory/assistant.py +++ b/cookbook/examples/personalization/assistant.py @@ -1,34 +1,43 @@ from typing import Optional -from phi.assistant import Assistant -from phi.knowledge import AssistantKnowledge +from phi.assistant import Assistant, AssistantMemory, AssistantKnowledge from phi.llm.openai import OpenAIChat from phi.tools.duckduckgo import DuckDuckGo from phi.embedder.openai import OpenAIEmbedder from phi.vectordb.pgvector import PgVector2 +from phi.memory.db.postgres import PgMemoryDb from phi.storage.assistant.postgres import PgAssistantStorage db_url = "postgresql+psycopg://ai:ai@localhost:5532/ai" -def get_auto_rag_assistant( - llm_model: str = "gpt-4-turbo", +def get_personalized_auto_rag_assistant( + llm_model: str = "gpt-4o", user_id: Optional[str] = None, run_id: Optional[str] = None, debug_mode: bool = True, ) -> Assistant: - """Get an Auto RAG Assistant.""" + """Get a Personalized Auto RAG Assistant.""" return Assistant( - name="auto_rag_assistant", + name="personalized_auto_rag_assistant", run_id=run_id, user_id=user_id, llm=OpenAIChat(model=llm_model), - storage=PgAssistantStorage(table_name="auto_rag_assistant_openai", db_url=db_url), + # Add personalization to the assistant + # by storing memories in a database and adding them to the system prompt + memory=AssistantMemory( + db=PgMemoryDb( + db_url=db_url, + table_name="personalized_auto_rag_assistant_memory", + ), + add_memories=True, + ), + storage=PgAssistantStorage(table_name="personalized_auto_rag_assistant_openai", db_url=db_url), knowledge_base=AssistantKnowledge( vector_db=PgVector2( db_url=db_url, - collection="auto_rag_documents_openai", + collection="personalized_auto_rag_documents_openai", embedder=OpenAIEmbedder(model="text-embedding-3-small", dimensions=1536), ), # 3 references are added to the prompt diff --git a/cookbook/examples/memory/requirements.in b/cookbook/examples/personalization/requirements.in similarity index 100% rename from cookbook/examples/memory/requirements.in rename to cookbook/examples/personalization/requirements.in diff --git a/cookbook/examples/memory/requirements.txt b/cookbook/examples/personalization/requirements.txt similarity index 99% rename from cookbook/examples/memory/requirements.txt rename to cookbook/examples/personalization/requirements.txt index ad3685e60..119abeb56 100644 --- a/cookbook/examples/memory/requirements.txt +++ b/cookbook/examples/personalization/requirements.txt @@ -107,7 +107,7 @@ pandas==2.2.2 # streamlit pgvector==0.2.5 # via -r cookbook/llms/openai/auto_rag/requirements.in -phidata==2.4.8 +phidata==2.4.10 # via -r cookbook/llms/openai/auto_rag/requirements.in pillow==10.3.0 # via streamlit diff --git a/cookbook/examples/research/requirements.txt b/cookbook/examples/research/requirements.txt index 882e76bb0..863ba06ab 100644 --- a/cookbook/examples/research/requirements.txt +++ b/cookbook/examples/research/requirements.txt @@ -99,7 +99,7 @@ pandas==2.2.2 # via # altair # streamlit -phidata==2.4.8 +phidata==2.4.10 # via -r cookbook/examples/research/requirements.in pillow==10.3.0 # via streamlit diff --git a/cookbook/examples/sql/requirements.txt b/cookbook/examples/sql/requirements.txt index aa62d6595..bd71bbca4 100644 --- a/cookbook/examples/sql/requirements.txt +++ b/cookbook/examples/sql/requirements.txt @@ -87,7 +87,7 @@ pandas==2.2.2 # streamlit pgvector==0.2.5 # via -r cookbook/examples/sql/requirements.in -phidata==2.4.8 +phidata==2.4.10 # via -r cookbook/examples/sql/requirements.in pillow==10.3.0 # via streamlit diff --git a/cookbook/examples/worldbuilding/requirements.txt b/cookbook/examples/worldbuilding/requirements.txt index 90b38f65c..8a5f20f58 100644 --- a/cookbook/examples/worldbuilding/requirements.txt +++ b/cookbook/examples/worldbuilding/requirements.txt @@ -95,7 +95,7 @@ pandas==2.2.0 # via # altair # streamlit -phidata==2.4.8 +phidata==2.4.10 # via -r cookbook/examples/worldbuilding/requirements.in pillow==10.2.0 # via streamlit diff --git a/cookbook/integrations/singlestore/ai_apps/requirements.txt b/cookbook/integrations/singlestore/ai_apps/requirements.txt index 1f22dea48..49c98cf8a 100644 --- a/cookbook/integrations/singlestore/ai_apps/requirements.txt +++ b/cookbook/integrations/singlestore/ai_apps/requirements.txt @@ -126,7 +126,7 @@ pandas==2.2.2 # yfinance peewee==3.17.3 # via yfinance -phidata==2.4.8 +phidata==2.4.10 # via -r cookbook/integrations/singlestore/auto_rag/requirements.in pillow==10.3.0 # via streamlit diff --git a/cookbook/llm_os/requirements.txt b/cookbook/llm_os/requirements.txt index c2e723c9a..20138d497 100644 --- a/cookbook/llm_os/requirements.txt +++ b/cookbook/llm_os/requirements.txt @@ -136,7 +136,7 @@ peewee==3.17.5 # via yfinance pgvector==0.2.5 # via -r cookbook/llm_os/requirements.in -phidata==2.4.8 +phidata==2.4.10 # via -r cookbook/llm_os/requirements.in pillow==10.3.0 # via diff --git a/cookbook/llms/groq/ai_apps/requirements.txt b/cookbook/llms/groq/ai_apps/requirements.txt index 60ec42b66..aa6465daa 100644 --- a/cookbook/llms/groq/ai_apps/requirements.txt +++ b/cookbook/llms/groq/ai_apps/requirements.txt @@ -127,7 +127,7 @@ peewee==3.17.3 # via yfinance pgvector==0.2.5 # via -r cookbook/llms/groq/ai_apps/requirements.in -phidata==2.4.8 +phidata==2.4.10 # via -r cookbook/llms/groq/ai_apps/requirements.in pillow==10.3.0 # via streamlit diff --git a/cookbook/llms/groq/auto_rag/requirements.txt b/cookbook/llms/groq/auto_rag/requirements.txt index c876d3095..20ecccf2f 100644 --- a/cookbook/llms/groq/auto_rag/requirements.txt +++ b/cookbook/llms/groq/auto_rag/requirements.txt @@ -113,7 +113,7 @@ pandas==2.2.2 # streamlit pgvector==0.2.5 # via -r cookbook/llms/groq/auto_rag/requirements.in -phidata==2.4.8 +phidata==2.4.10 # via -r cookbook/llms/groq/auto_rag/requirements.in pillow==10.3.0 # via streamlit diff --git a/cookbook/llms/groq/investment_researcher/requirements.txt b/cookbook/llms/groq/investment_researcher/requirements.txt index 394c4092f..e8f565bb0 100644 --- a/cookbook/llms/groq/investment_researcher/requirements.txt +++ b/cookbook/llms/groq/investment_researcher/requirements.txt @@ -124,7 +124,7 @@ pandas==2.2.2 # yfinance peewee==3.17.3 # via yfinance -phidata==2.4.8 +phidata==2.4.10 # via -r cookbook/llms/groq/investment_researcher/requirements.in pillow==10.3.0 # via streamlit diff --git a/cookbook/llms/groq/news_articles/requirements.txt b/cookbook/llms/groq/news_articles/requirements.txt index 89d8d56a2..332bcdcd8 100644 --- a/cookbook/llms/groq/news_articles/requirements.txt +++ b/cookbook/llms/groq/news_articles/requirements.txt @@ -119,7 +119,7 @@ pandas==2.2.2 # altair # newspaper4k # streamlit -phidata==2.4.8 +phidata==2.4.10 # via -r cookbook/llms/groq/news_articles/requirements.in pillow==10.3.0 # via diff --git a/cookbook/llms/groq/rag/requirements.txt b/cookbook/llms/groq/rag/requirements.txt index 1aad73041..1bfcb467e 100644 --- a/cookbook/llms/groq/rag/requirements.txt +++ b/cookbook/llms/groq/rag/requirements.txt @@ -111,7 +111,7 @@ pandas==2.2.2 # streamlit pgvector==0.2.5 # via -r cookbook/llms/groq/rag/requirements.in -phidata==2.4.8 +phidata==2.4.10 # via -r cookbook/llms/groq/rag/requirements.in pillow==10.3.0 # via streamlit diff --git a/cookbook/llms/groq/research/requirements.txt b/cookbook/llms/groq/research/requirements.txt index 3ef4f4479..75a776abe 100644 --- a/cookbook/llms/groq/research/requirements.txt +++ b/cookbook/llms/groq/research/requirements.txt @@ -85,7 +85,7 @@ pandas==2.2.2 # via # altair # streamlit -phidata==2.4.8 +phidata==2.4.10 # via -r cookbook/llms/groq/research/requirements.in pillow==10.3.0 # via streamlit diff --git a/cookbook/llms/groq/video_summary/requirements.txt b/cookbook/llms/groq/video_summary/requirements.txt index 3d7e88058..35adaf0b8 100644 --- a/cookbook/llms/groq/video_summary/requirements.txt +++ b/cookbook/llms/groq/video_summary/requirements.txt @@ -85,7 +85,7 @@ pandas==2.2.2 # via # altair # streamlit -phidata==2.4.8 +phidata==2.4.10 # via -r cookbook/llms/groq/video_summary/requirements.in pillow==10.3.0 # via streamlit diff --git a/cookbook/llms/hermes2/auto_rag/requirements.txt b/cookbook/llms/hermes2/auto_rag/requirements.txt index c7314d5c0..512786967 100644 --- a/cookbook/llms/hermes2/auto_rag/requirements.txt +++ b/cookbook/llms/hermes2/auto_rag/requirements.txt @@ -98,7 +98,7 @@ pandas==2.2.0 # streamlit pgvector==0.2.4 # via -r cookbook/llms/hermes2/auto_rag/requirements.in -phidata==2.4.8 +phidata==2.4.10 # via -r cookbook/llms/hermes2/auto_rag/requirements.in pillow==10.2.0 # via streamlit diff --git a/cookbook/llms/mistral/rag/requirements.txt b/cookbook/llms/mistral/rag/requirements.txt index de8095fdb..79eb6f566 100644 --- a/cookbook/llms/mistral/rag/requirements.txt +++ b/cookbook/llms/mistral/rag/requirements.txt @@ -98,7 +98,7 @@ pandas==2.2.2 # streamlit pgvector==0.2.5 # via -r cookbook/llms/mistral/rag/requirements.in -phidata==2.4.8 +phidata==2.4.10 # via -r cookbook/llms/mistral/rag/requirements.in pillow==10.3.0 # via streamlit diff --git a/cookbook/llms/ollama/auto_rag/requirements.txt b/cookbook/llms/ollama/auto_rag/requirements.txt index f8dac96f7..ed2160252 100644 --- a/cookbook/llms/ollama/auto_rag/requirements.txt +++ b/cookbook/llms/ollama/auto_rag/requirements.txt @@ -100,7 +100,7 @@ pandas==2.2.2 # streamlit pgvector==0.2.5 # via -r cookbook/llms/ollama/auto_rag/requirements.in -phidata==2.4.8 +phidata==2.4.10 # via -r cookbook/llms/ollama/auto_rag/requirements.in pillow==10.3.0 # via streamlit diff --git a/cookbook/llms/ollama/rag/requirements.txt b/cookbook/llms/ollama/rag/requirements.txt index f948c965c..8d8b30a77 100644 --- a/cookbook/llms/ollama/rag/requirements.txt +++ b/cookbook/llms/ollama/rag/requirements.txt @@ -96,7 +96,7 @@ pandas==2.2.2 # streamlit pgvector==0.2.5 # via -r cookbook/llms/ollama/rag/requirements.in -phidata==2.4.8 +phidata==2.4.10 # via -r cookbook/llms/ollama/rag/requirements.in pillow==10.3.0 # via streamlit diff --git a/cookbook/llms/ollama/tools/requirements.txt b/cookbook/llms/ollama/tools/requirements.txt index 011a48a0e..e76f694af 100644 --- a/cookbook/llms/ollama/tools/requirements.txt +++ b/cookbook/llms/ollama/tools/requirements.txt @@ -114,7 +114,7 @@ peewee==3.17.3 # via yfinance pgvector==0.2.5 # via -r cookbook/llms/ollama/tools/requirements.in -phidata==2.4.8 +phidata==2.4.10 # via -r cookbook/llms/ollama/tools/requirements.in pillow==10.3.0 # via streamlit diff --git a/cookbook/llms/ollama/video_summary/requirements.txt b/cookbook/llms/ollama/video_summary/requirements.txt index 3f96fc9f7..60b629b4a 100644 --- a/cookbook/llms/ollama/video_summary/requirements.txt +++ b/cookbook/llms/ollama/video_summary/requirements.txt @@ -84,7 +84,7 @@ pandas==2.2.2 # streamlit pgvector==0.2.5 # via -r cookbook/llms/ollama/video_summary/requirements.in -phidata==2.4.8 +phidata==2.4.10 # via -r cookbook/llms/ollama/video_summary/requirements.in pillow==10.3.0 # via streamlit diff --git a/cookbook/llms/openai/auto_rag/requirements.txt b/cookbook/llms/openai/auto_rag/requirements.txt index ad3685e60..119abeb56 100644 --- a/cookbook/llms/openai/auto_rag/requirements.txt +++ b/cookbook/llms/openai/auto_rag/requirements.txt @@ -107,7 +107,7 @@ pandas==2.2.2 # streamlit pgvector==0.2.5 # via -r cookbook/llms/openai/auto_rag/requirements.in -phidata==2.4.8 +phidata==2.4.10 # via -r cookbook/llms/openai/auto_rag/requirements.in pillow==10.3.0 # via streamlit diff --git a/phi/assistant/assistant.py b/phi/assistant/assistant.py index 662df14ed..0fca4e839 100644 --- a/phi/assistant/assistant.py +++ b/phi/assistant/assistant.py @@ -325,6 +325,10 @@ def load_memory(self) -> None: self.memory.user_id = self.user_id self.memory.load_memory() + if self.user_id is not None: + logger.debug(f"Loaded memory for user: {self.user_id}") + else: + logger.debug("Loaded memory") def to_database_row(self) -> AssistantRun: """Create a AssistantRun for the current Assistant (to save to the database)""" @@ -436,6 +440,7 @@ def read_from_storage(self) -> Optional[AssistantRun]: logger.debug(f"-*- Loading run: {self.db_row.run_id}") self.from_database_row(row=self.db_row) logger.debug(f"-*- Loaded run: {self.run_id}") + self.load_memory() return self.db_row def write_to_storage(self) -> Optional[AssistantRun]: @@ -672,7 +677,7 @@ def get_system_prompt(self) -> Optional[str]: system_prompt_lines.append( "Note: this information is from previous interactions and may be updated during this conversation. You should always prefer information from this conversation over the memories." ) - system_prompt_lines.append("If you need to update the memory, use the 'update_memory' tool.") + system_prompt_lines.append("If you need to update the long-term memory, use the 'update_memory' tool.") else: system_prompt_lines.append( "\nYou also have access to memory from previous interactions with the user but the user has no memories yet." @@ -806,9 +811,6 @@ def _run( # Load run from storage self.read_from_storage() - # Load Memory - self.load_memory() - # Update the LLM (set defaults, add tools, etc.) self.update_llm() @@ -891,7 +893,8 @@ def _run( if user_message is not None: self.memory.add_chat_message(message=user_message) # Update the memory with the user message if needed - self.memory.update_memory(input=user_message.get_content_string()) + if self.memory.update_memory_after_run: + self.memory.update_memory(input=user_message.get_content_string()) # Build the LLM response message to add to the memory - this is added to the chat_history llm_response_message = Message(role="assistant", content=llm_response) @@ -1077,9 +1080,6 @@ async def _arun( async for response_chunk in response_stream: # type: ignore llm_response += response_chunk yield response_chunk - # async for response_chunk in await self.llm.aresponse_stream(messages=llm_messages): - # llm_response += response_chunk - # yield response_chunk else: llm_response = await self.llm.aresponse(messages=llm_messages) @@ -1090,6 +1090,9 @@ async def _arun( # Add user message to the memory if user_message is not None: self.memory.add_chat_message(message=user_message) + # Update the memory with the user message if needed + if self.memory.update_memory_after_run: + self.memory.update_memory(input=user_message.get_content_string()) # Build the LLM response message to add to the memory - this is added to the chat_history llm_response_message = Message(role="assistant", content=llm_response) diff --git a/phi/memory/assistant.py b/phi/memory/assistant.py index b0e15e620..c9912eb61 100644 --- a/phi/memory/assistant.py +++ b/phi/memory/assistant.py @@ -37,6 +37,7 @@ class AssistantMemory(BaseModel): classifier: Optional[MemoryClassifier] = None manager: Optional[MemoryManager] = None updating: bool = False + update_memory_after_run: bool = True model_config = ConfigDict(arbitrary_types_allowed=True) diff --git a/phi/memory/classifier.py b/phi/memory/classifier.py index 4ba765e30..931f41939 100644 --- a/phi/memory/classifier.py +++ b/phi/memory/classifier.py @@ -36,14 +36,14 @@ def get_system_prompt(self) -> Optional[str]: # -*- Build a default system prompt for classification system_prompt_lines = [ - "Your task is to analyze the user's message and determine if the long-term memory should be updated.", - "Long-term memory contains information worth remembering for future conversations." - "It includes a broad range of details that could enhance the quality and personalization of ongoing interactions, such as:\n" + "Your task is to analyze the user's message and determine if it is worth remembering for future conversations.", + "The goal is to identify any noteworthy information that could be useful for personalizing the user experience.", + "This includes a broad range of details that could enhance the quality and personalization of ongoing interactions, such as:\n" " - Personal facts: name, age, occupation, location, interests, preferences, etc.\n" " - Significant life events or experiences shared by the user\n" " - Important context about the user's current situation, challenges or goals\n" " - Any other details that provide valuable insights into the user's personality, perspective or needs", - "If the user input contains any such noteworthy information, respond with 'yes' to update the long-term memory.", + "If the user input contains any such noteworthy information, respond with 'yes' to add it to the long-term memory.", "If the input does not contain any important details worth saving, respond with 'no' to disregard it.", "You will also be provided with a list of existing memories to help you make an informed decision.", "If the memory already exists that matches the input, respond with 'no' to keep it as is.", diff --git a/phi/memory/manager.py b/phi/memory/manager.py index ea02016ab..e057ed20d 100644 --- a/phi/memory/manager.py +++ b/phi/memory/manager.py @@ -123,14 +123,12 @@ def get_system_prompt(self) -> Optional[str]: "Your task is to generate a concise memory for the user's message. " "Create a memory that captures the key information provided by the user, as if you were storing it for future reference. " "The memory should be a brief, third-person statement that encapsulates the most important aspect of the user's input, without adding any extraneous details. " - "Your goal is to create a memory that can be effectively used to enhance the user's experience in subsequent conversations.", - "You will also be provided with a list of existing memories. Follow these steps to manage the memories:", - " 1. If the input does not match any existing memories, add a new memory using the `add_memory` tool.", - " 2. If the user input matches an existing memory that should be updated, update it using the `update_memory` tool.", - " 3. If the user input matches an existing memory that should be deleted, delete it using the `delete_memory` tool.", - "Make sure to review the existing memories carefully before making a decision.", - "Clean up any unnecessary or outdated memories to ensure that the memory database remains relevant and useful. Add, Update or Delete a memory as needed.", - "You can clear all memories using the `clear_memory` tool. Use this option with caution, as it will remove all memories from the database.", + "This memory will be used to enhance the user's experience in subsequent conversations.", + "You will also be provided with a list of existing memories. You may:", + " 1. Add a new memory using the `add_memory` tool.", + " 2. Update a memory using the `update_memory` tool.", + " 3. Delete a memory using the `delete_memory` tool.", + " 4. Clear all memories using the `clear_memory` tool. Use this with extreme caution, as it will remove all memories from the database.", ] existing_memories = self.get_existing_memories() if existing_memories and len(existing_memories) > 0: