Nous is an open-source personal knowledge assistant that allows you to interact with your personal documents and text files using natural language. It's designed with a focus on privacy, security, and local processing.
Note: For the demo, I personalized Nous using the Lord of the Rings Trilogy PDF.
- Talk to Your Documents: Interact with your personal knowledge base through natural language queries.
- Local Processing: Uses local LLMs for enhanced privacy and security.
- Self-Corrective RAG: Implements a Corrective RAG (CRAG) system for accurate information retrieval and response generation.
- Web Search Integration: Falls back to web search when local knowledge is insufficient.
- Document Ingestion: Supports various document sources including Google Docs, Google Drive, Dropbox, and GitHub gists.
Nous consists of two main services:
-
LLM Service (Flask App):
- Manages communication with local LLMs via Ollama
- Implements the Corrective RAG (CRAG) system
- Uses LangGraph and Langchain for agentic workflow
- Utilizes FAISS as the vector database
- Employs Phi3-mini and TinyLlama as local LLMs
- Uses the nomic model for embeddings
- Integrates Tavily for web search capabilities
-
HTTP Web Server (Golang with Gin):
- Renders the UI using HTMX
- Stores chat sessions and messages in SQLite
- Utilizes Redis for query caching
- Implements Levenshtein distance for efficient string matching on recent queries
.
├── Dockerfile.ollama
├── LICENSE
├── ReadMe.md
├── app # Golang HTTP server
│ ├── Dockerfile
│ ├── Makefile
│ ├── cmd
│ ├── db
│ ├── go.mod
│ ├── go.sum
│ ├── internal
│ ├── nous.db
│ ├── static
├── docker-compose.yml
├── docs
│ ├── crag-architecture.png
│ ├── nous-architecture.png
│ └── nous-demo.gif
├── llm_api # Flask app; LLM service
│ ├── Dockerfile
│ ├── __pycache__
│ ├── app.py
│ ├── config.py
│ ├── data
│ ├── document_processor.py
│ ├── embeddings.py
│ ├── graph.py
│ ├── llm.py
│ ├── llm_env
│ ├── main.py
│ ├── prompts.py
│ ├── requirements.txt
│ └── retriever.py
└── start-ollama.sh
- Local LLMs: Phi3-mini, TinyLlama
- Vector Database: FAISS
- Embedding Model: Nomic
- Web Search: Tavily
- Web Server: Golang with Gin
- Frontend Rendering: HTMX (with Go Templ)
- Cache: Redis
- Database: SQLite
- Workflow: LangGraph, Langchain
- Communication with LLMs: Ollama
- Docker and Docker Compose
- Ollama (for local development only)
-
Clone the repository:
git clone https://github.com/ramchaik/nous.git cd nous
-
Create a
.env
file in the llm_api directory with the following content:TAVILY_API_KEY=your_tavily_api_key_here
-
Run the entire setup with Docker Compose:
docker-compose up --build
This command will:
- Build and start the Ollama service
- Start a Redis container
- Build and start the LLM service (Flask app)
- Build and start the Golang app
-
Access the Nous web interface at
http://localhost:8080
If you prefer to run the services locally for development:
-
Set up Ollama:
ollama pull phi3:mini tinyllama nomic-embed-text ollama serve
-
Start Redis server:
docker run --name redis -p 6379:6379 -d redis
-
Set up LLM service:
cd llm_api python -m venv llm_env source llm_env/bin/activate pip install -r requirements.txt python app.py
-
Set up Golang app:
cd app make run
To add your personal links for Nous to process:
- Open the
llm_api/config.py
file. - Locate the
KNOWLEDGE_BASE_URLS
list in the file. - Add your personal URLs to this list.
- Save the file and restart the Flask app for changes to take effect.
Example:
KNOWLEDGE_BASE_URLS = [
"https://your-personal-link.com/document.pdf",
"https://another-personal-link.com/notes.txt"
]
After adding your links, restart the Flask app to ingest the new documents into the vector database.
Nous uses two main configuration files: one for the Golang HTTP server and another for the Python Flask LLM service.
Located at: app/internal/config/config.go
The Golang server configuration manages various aspects of the web server, including paths, addresses, and connections.
type Config struct {
StaticPath string
ServerAddr string
DatabasePath string
LLMBaseURL string
RedisAddr string
}
StaticPath
: Path to static files (default:"../static"
relative to the executable)ServerAddr
: Address and port for the HTTP server (default::8080
)DatabasePath
: Path to the SQLite database file (default:"./nous.db"
)LLMBaseURL
: URL of the LLM service (default:"http://localhost:5000"
)RedisAddr
: Address of the Redis server (default:"localhost:6379"
)
You can customize these settings using environment variables:
STATIC_PATH
: Set the path to static filesSERVER_ADDR
: Set the server address and portDATABASE_PATH
: Set the path to the SQLite database fileLLM_BASE_URL
: Set the URL of the LLM serviceREDIS_ADDR
: Set the address of the Redis server
Example:
export SERVER_ADDR=:8081
Located at: llm_api/config.py
The LLM service configuration controls the behavior of the Flask app that manages LLM interactions.
-
API Keys
TAVILY_API_KEY = os.getenv("TAVILY_API_KEY")
- Used for web search capabilities. Set this in your
.env
file.
- Used for web search capabilities. Set this in your
-
Vectorstore Paths
DATA_INDEX_PATH = os.getenv('DATA_INDEX_PATH', "data/faiss_index.bin") DATA_VECTOR_PATH = os.getenv('DATA_VECTOR_PATH', "data/vectors.npy") DATA_INDEX_TO_ID_PATH = os.getenv('DATA_INDEX_TO_ID_PATH', "data/index_to_id.npy")
- Determine where vectorstore data is saved and loaded from.
-
Ollama Configuration
class OllamaConfig: HOST = os.getenv('OLLAMA_HOST', 'http://localhost:11434') EMBEDDINGS_MODEL = os.getenv('OLLAMA_EMBEDDINGS_MODEL', "nomic-embed-text") MODEL_RAG = os.getenv('OLLAMA_MODEL_RAG', "phi3:mini") MODEL_RETRIEVER_GRADER = os.getenv('OLLAMA_MODEL_RETRIEVER_GRADER', "thinyllama:mini")
HOST
: URL where Ollama is runningEMBEDDINGS_MODEL
: Model for generating embeddingsMODEL_RAG
: Model for Retrieval-Augmented GenerationMODEL_RETRIEVER_GRADER
: Model for grading retrieval results
-
Personal Knowledge Base Resources
KNOWLEDGE_BASE_URLS = [ "https://your-personal-link.com/document.pdf", "https://another-personal-link.com/notes.txt" ]
- List of URLs for documents to be ingested into the knowledge base.
To modify LLM service settings:
- Open
llm_api/config.py
in a text editor. - Adjust values as needed.
- For environment variables, either:
- Set them in your system environment, or
- Create a
.env
file in thellm_api
directory with the required key-value pairs.
- Save the file and restart the LLM service.
After modifying any configuration:
- For the Golang server, rebuild and restart the server.
- For the LLM service, restart the Flask app.
- If using Docker, rebuild the containers:
docker-compose up --build
This ensures that all configuration changes are properly incorporated into the running services.
The docker-compose.yml
file in the root directory contains the following services:
ollama
: Runs the Ollama service for local LLMsredis
: Provides caching capabilitiesllm_service
: The Flask app that manages LLM interactionsgolang_app
: The main web server written in Go
To customize the setup, you can modify the docker-compose.yml
file. For example, to change the exposed port of the Golang app:
golang_app:
# ... other configurations ...
ports:
- "8081:8080" # Change 8081 to your desired port
Remember to rebuild the services after making changes:
docker-compose up --build
- Add support for uploading links directly from the UI for ingestion into the vector store
- Implement source attribution in the chat UI for web sources to improve transparency
- Expand support to include more document formats such as Excel, Markdown, and LaTeX.
- Integrate additional LLMs for improved response diversity and quality.
- Introduce customizable workflows for specific use cases, such as study aids or meeting summaries.
Nous was created to provide a seamless and secure way to interact with personal notes and documents. It prioritizes local processing and privacy while offering powerful knowledge retrieval and interaction capabilities.
Contributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under the MIT License.