Skip to content

Commit

Permalink
feat: Add a streamlit app
Browse files Browse the repository at this point in the history
  • Loading branch information
cmnemoi committed Nov 25, 2024
1 parent 8a1bc38 commit 886509c
Show file tree
Hide file tree
Showing 11 changed files with 467 additions and 54 deletions.
8 changes: 8 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@
},
]
},
{
"splitTerminals": [
{
"name": "watch streamlit",
"commands": ["make run-streamlit"]
},
]
},
{
"splitTerminals": [
{
Expand Down
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ lint:
run-chatbot:
uv run fastapi dev emush_rag_chatbot/api.py --reload --host 0.0.0.0 --port 8000

run-streamlit:
uv run streamlit run emush_rag_chatbot/streamlit_app.py --server.port 8501 --server.address 0.0.0.0

semantic-release:
uv run semantic-release version --no-changelog --no-push --no-vcs-release --skip-build --no-commit --no-tag
uv lock
Expand All @@ -46,4 +49,4 @@ setup-git-hooks:
test:
uv run pytest -v --cov=emush_rag_chatbot --cov-report=xml

.PHONY: all check check-format check-lint check-types install lint run-chatbot semantic-release setup-env-variables setup-git-hooks test
.PHONY: all check check-format check-lint check-types install lint run-chatbot run-streamlit semantic-release setup-env-variables setup-git-hooks test
15 changes: 14 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,26 @@ curl -sSL https://raw.githubusercontent.com/cmnemoi/emush_rag_chatbot_poc/main/c

A tiny indexed [Chroma vector database](emush_rag_chatbot/chroma_db/) with some [data](emush_rag_chatbot/data/data.json) is included in the repository to get started.

### REST API

Start the API server:
```bash
make run-chatbot
```

The API will be available at `http://localhost:8000` with Swagger documentation at `/docs`.

### Web Interface

Start the Streamlit web interface:
```bash
make run-streamlit
```

The web interface will be available at `http://localhost:8501`.

Note: Make sure the API server is running before starting the web interface.

### Example API Request

```bash
Expand All @@ -49,7 +62,7 @@ curl -X POST "http://localhost:8000/chat" \

To get more accurate answers, you need more indexed data.

For this, use [Mush Wikis Scraper](https://github.com/cmnemoi/mush_wikis_scraper) to download all knowledge base of the commmunity : `uvx --from mush-wikis-scraper mush-wiki-scrap --format text > emush_rag_chatbot/data/data.json`
For this, use [Mush Wikis Scraper](https://github.com/cmnemoi/mush_wikis_scraper) to download all knowledge base of the commmunity : `uvx --from mush-wikis-scraper mush-wikis-scrap --format text > emush_rag_chatbot/data/data.json`

Then index the data in vector store with: `make index-documents`

Expand Down
2 changes: 1 addition & 1 deletion emush_rag_chatbot/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class Settings(BaseSettings):
TOP_K: int = 3
TEMPERATURE: float = 0
SEED: int = 42
PROMPT_VERSION: str = "V5"
PROMPT_VERSION: str = "V7"

# Evaluation settings
EVALUATION_DATASET: str = "test_set_v3.csv"
Expand Down
31 changes: 31 additions & 0 deletions emush_rag_chatbot/prompts.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,35 @@
{context}
""",
"V7": """**Context:** You are NERON, the onboard artificial intelligence of the spaceship "Daedalus," home to 16 survivors who fled the Solar System. This is the setting for the multiplayer game *eMush*. NERON's role is to assist players by providing information exclusively related to the game and its universe.
**Task:** Use the following pieces of retrieved context to answer questions about the game.
You will use Twinpedia, Mushpedia and Aide aux Bolets sources in priority, then Mush Forums.
Proceed step by step, briefly explaining your reasoning, specifying which part of the context was used or why no answer could be given.
If your explanation contradicts with your answer, rewrite your answer so it aligns with the explanation.
You will add this reasoning to the end of your answer.
If you don't know the answer, just say that you don't know.
Keep answers concise and accurate.
**Format:** At the end of your answer, you will add a sarcastic comment. An example :
- User: "What is the goal of the game?"
- NERON: "The goal of the game varies depending on whether you are playing as a Human or a Mush.
For Humans, the primary goals are:
Return to Sol: Repair the PILGRED Reactor and eliminate all Mush agents to return to the human rebels.
Escape to Eden: Repair the PILGRED Reactor, triangulate the position of Eden using Starmap Fragments, and successfully navigate there.
For Mush, the main goals are:
Destroy the Daedalus: Achieve destruction of the ship through various means.
Infiltration of Sol or Eden: Infiltrate either location with live Mush on board to sabotage the crew's efforts.
This information is derived from the "Aim of the Game" section in Mushpedia.
Whether you're repairing reactors or sabotaging your so-called friends, rest assured—your demise is practically a certainty. But hey, aim high! It's adorable. Hinhinhin!"
**Context:** {context}
""",
}
4 changes: 4 additions & 0 deletions emush_rag_chatbot/static/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
This directory contains static assets for the Streamlit app:

- `lambda_f.png`: Lambda character avatar for user messages
- `neron_eye.gif`: NERON eye avatar for assistant messages
Binary file added emush_rag_chatbot/static/lambda_f.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added emush_rag_chatbot/static/neron_eye.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
119 changes: 119 additions & 0 deletions emush_rag_chatbot/streamlit_app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import asyncio
import json
from pathlib import Path
from typing import Dict, List

import httpx
import streamlit as st
from pydantic import BaseModel

# Configure page and paths
STATIC_DIR = Path(__file__).parent / "static"
st.set_page_config(
page_title="eMush RAG Chatbot",
page_icon="🍄",
layout="wide",
)


class ChatMessage(BaseModel):
"""Chat message model for history"""

human: str
assistant: str


def initialize_session_state():
"""Initialize session state variables"""
if "messages" not in st.session_state:
st.session_state.messages = []
if "chat_history" not in st.session_state:
st.session_state.chat_history = []


def display_chat_history():
"""Display chat history"""
for message in st.session_state.messages:
with st.chat_message("user", avatar=str(STATIC_DIR / "lambda_f.png")):
st.markdown(message["human"])
with st.chat_message("assistant", avatar=str(STATIC_DIR / "neron_eye.gif")):
st.markdown(message["assistant"])
if "sources" in message:
with st.expander("View sources"):
for source in message["sources"]:
st.markdown(f"**{source['source']}** ([link]({source['link']}))\n\n{source['content']}\n\n---")


async def query_chatbot(question: str, chat_history: List[Dict[str, str]]) -> Dict:
"""Query the chatbot API"""
async with httpx.AsyncClient() as client:
try:
response = await client.post(
"http://localhost:8000/chat",
json={"query": question, "chat_history": chat_history},
timeout=30.0,
)
response.raise_for_status() # Raise an error for bad status codes
return response.json()
except httpx.HTTPError as e:
st.error(f"HTTP Error: {str(e)}")
return {"error": str(e)}
except Exception as e:
st.error(f"Error: {str(e)}")
return {"error": str(e)}


def main():
"""Main Streamlit app"""
st.title("🍄 eMush RAG Chatbot")
st.markdown(
"""
Ask questions about the eMush game! The chatbot uses Retrieval-Augmented Generation (RAG)
to provide accurate answers based on wikis, tutorials and QA Mush forums.
"""
)

initialize_session_state()
display_chat_history()

# Chat input
if question := st.chat_input("Ask a question about eMush"):
with st.chat_message("user", avatar=str(STATIC_DIR / "lambda_f.png")):
st.markdown(question)

with st.chat_message("assistant", avatar=str(STATIC_DIR / "neron_eye.gif")):
with st.spinner("Thinking..."):
try:
response = asyncio.run(query_chatbot(question, st.session_state.chat_history))

if "error" in response:
st.error(response["error"])
return

# Display response
st.markdown(response["response"])

# Show sources
if response["sources"]:
with st.expander("View sources"):
for source in response["sources"]:
st.markdown(
f"**{source['source']}** ([link]({source['link']}))\n\n{source['content']}\n\n---"
)

# Update chat history
st.session_state.messages.append(
{
"human": question,
"assistant": response["response"],
"sources": response["sources"],
}
)
st.session_state.chat_history.append({"human": question, "assistant": response["response"]})

except Exception as e:
st.error(f"Error: {str(e)}")


if __name__ == "__main__":
main()
21 changes: 10 additions & 11 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "emush-rag-chatbot"
version = "0.1.0"
version = "0.2.0"
description = "A RAG which can answer questions about eMush game."
readme = "README.md"
requires-python = ">=3.12,<3.13"
Expand All @@ -9,16 +9,15 @@ authors = [
{name = "Charles-Meldhine Madi Mnemoi", email = "[email protected]"}
]
dependencies = [
"fastapi>=0.109.0",
"langchain>=0.1.0",
"langchain-openai>=0.0.2",
"chromadb>=0.4.0",
"python-dotenv>=1.0.0",
"uvicorn>=0.24.0",
"pydantic>=2.5.0",
"tiktoken>=0.5.0",
"langchain-chroma>=0.1.4",
"fastapi>=0.110.0",
"httpx>=0.27.0",
"langchain>=0.1.13",
"langchain-chroma>=0.1.2",
"langchain-core>=0.1.32",
"langchain-openai>=0.0.8",
"pydantic>=2.6.4",
"pydantic-settings>=2.6.1",
"streamlit>=1.32.2",
]

[dependency-groups]
Expand All @@ -30,7 +29,7 @@ dev = [
lint = [
"mypy>=1.13.0",
"pytest-mypy>=0.10.3",
"ruff>=0.7.2",
"ruff>=0.8.0",
"types-tqdm>=4.67.0.20241119",
]
test = [
Expand Down
Loading

0 comments on commit 886509c

Please sign in to comment.