This commit is contained in:
@@ -1,12 +1,14 @@
|
|||||||
# Agent with RAG Memory
|
# RAG Agent with LangChain, Qdrant, and Ollama
|
||||||
|
|
||||||
This project demonstrates a simple RAG (Retrieval-Augmented Generation) agent that uses LangChain tools to perform basic operations via an interactive command line interface (CLI).
|
This repository contains a minimal example of a Retrieval-Augmented Generation (RAG) agent built with **LangChain**, **Qdrant**, and **Ollama**. The agent retrieves relevant documents from a local Qdrant vector store and generates answers using an Ollama language model.
|
||||||
|
|
||||||
## Features
|
## Prerequisites
|
||||||
|
|
||||||
- **Add Numbers** – Add two integers using the `add_numbers` tool.
|
- **Python 3.10+**
|
||||||
- **Search Items** – Search a predefined list of strings for a query using the `search_item` tool.
|
- **Qdrant** server running locally (default port `6333`).
|
||||||
- **Interactive CLI** – Use `/add`, `/search`, and `/quit` commands to interact with the agent.
|
- Create a collection named `rag_collection` and populate it with embeddings.
|
||||||
|
- **Ollama** server running locally (default port `11434`).
|
||||||
|
- Ensure the model `llama3.1` (or any other supported model) is available.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
@@ -17,7 +19,7 @@ cd agent-s-rag-pamyatyu
|
|||||||
|
|
||||||
# Create a virtual environment (optional but recommended)
|
# Create a virtual environment (optional but recommended)
|
||||||
python -m venv .venv
|
python -m venv .venv
|
||||||
source .venv/bin/activate # On Windows use `.venv\\Scripts\\activate`
|
source .venv/bin/activate # On Windows: .venv\\Scripts\\activate
|
||||||
|
|
||||||
# Install dependencies
|
# Install dependencies
|
||||||
pip install -r requirements.txt
|
pip install -r requirements.txt
|
||||||
@@ -25,72 +27,34 @@ pip install -r requirements.txt
|
|||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
Run the CLI:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python -m src.main
|
python -m src.main
|
||||||
```
|
```
|
||||||
|
|
||||||
You will see a prompt:
|
You will be prompted to enter a question. The agent will retrieve relevant documents from Qdrant and generate an answer using Ollama. Type `exit` or `quit` to terminate the program.
|
||||||
|
|
||||||
```
|
|
||||||
Welcome to the RAG Agent CLI!
|
|
||||||
Available commands:
|
|
||||||
/add <int> <int> - Add two numbers.
|
|
||||||
/search <query> - Search items in memory.
|
|
||||||
/quit - Exit the program.
|
|
||||||
```
|
|
||||||
|
|
||||||
### Commands
|
|
||||||
|
|
||||||
- **/add**
|
|
||||||
Add two integers.
|
|
||||||
|
|
||||||
```text
|
|
||||||
>> /add 5 7
|
|
||||||
Result: 12
|
|
||||||
```
|
|
||||||
|
|
||||||
- **/search**
|
|
||||||
Search the internal memory for a query string.
|
|
||||||
|
|
||||||
```text
|
|
||||||
>> /search python
|
|
||||||
Matches found:
|
|
||||||
1. Python programming
|
|
||||||
```
|
|
||||||
|
|
||||||
- **/quit**
|
|
||||||
Exit the program.
|
|
||||||
|
|
||||||
```text
|
|
||||||
>> /quit
|
|
||||||
Goodbye!
|
|
||||||
```
|
|
||||||
|
|
||||||
## Project Structure
|
## Project Structure
|
||||||
|
|
||||||
```
|
```
|
||||||
agent-s-rag-pamyatyu/
|
agent-s-rag-pamyatyu/
|
||||||
├── src/
|
|
||||||
│ ├── __init__.py
|
|
||||||
│ ├── cli.py
|
|
||||||
│ ├── main.py
|
|
||||||
│ └── tools.py
|
|
||||||
├── README.md
|
|
||||||
├── requirements.txt
|
├── requirements.txt
|
||||||
└── pyproject.toml
|
├── src/
|
||||||
|
│ └── main.py
|
||||||
|
└── README.md
|
||||||
```
|
```
|
||||||
|
|
||||||
## Dependencies
|
- `requirements.txt` – lists all Python dependencies, including `langchain-qdrant` and `langchain-ollama`.
|
||||||
|
- `src/main.py` – contains the RAG agent implementation.
|
||||||
|
- `README.md` – this documentation file.
|
||||||
|
|
||||||
- `langchain` – The core library for building language model agents.
|
## Troubleshooting
|
||||||
- `python-dotenv` – (Optional) For loading environment variables if needed.
|
|
||||||
|
- **Missing dependencies**: Ensure you ran `pip install -r requirements.txt`.
|
||||||
|
- **Qdrant connection errors**: Verify Qdrant is running and the collection name matches `rag_collection`.
|
||||||
|
- **Ollama connection errors**: Verify Ollama is running and the model name is correct.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
MIT License
|
This project is provided as-is for educational purposes. Feel free to modify and extend it.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
Feel free to extend the tools or the CLI to suit your needs!
|
|
||||||
+5
-2
@@ -1,2 +1,5 @@
|
|||||||
langchain>=0.0.0
|
langchain>=0.2.0
|
||||||
python-dotenv>=0.21.0
|
langchain-qdrant>=0.1.0
|
||||||
|
langchain-ollama>=0.1.0
|
||||||
|
qdrant-client>=1.0.0
|
||||||
|
pydantic>=2.0.0
|
||||||
+106
-2
@@ -1,7 +1,111 @@
|
|||||||
from .cli import run_cli
|
"""
|
||||||
|
Simple RAG agent using LangChain, Qdrant, and Ollama.
|
||||||
|
|
||||||
|
This script demonstrates how to set up a retrieval-augmented generation (RAG) pipeline
|
||||||
|
with a local Qdrant vector store and an Ollama LLM. It can be run directly:
|
||||||
|
|
||||||
|
python -m src.main
|
||||||
|
|
||||||
|
The script will prompt the user for a question and return an answer based on the
|
||||||
|
documents stored in Qdrant.
|
||||||
|
|
||||||
|
Prerequisites:
|
||||||
|
- Qdrant server running locally (default port 6333).
|
||||||
|
- Ollama server running locally (default port 11434).
|
||||||
|
- A Qdrant collection named "rag_collection" populated with embeddings.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
try:
|
||||||
|
from langchain_ollama import OllamaLLM
|
||||||
|
from langchain_qdrant import QdrantStore
|
||||||
|
from langchain.chains import RetrievalQA
|
||||||
|
from langchain.memory import ConversationBufferMemory
|
||||||
|
except ImportError as e:
|
||||||
|
print("Required packages are missing. Please run 'pip install -r requirements.txt'.")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
def get_llm() -> OllamaLLM:
|
||||||
|
"""
|
||||||
|
Create an Ollama LLM instance.
|
||||||
|
"""
|
||||||
|
# Ollama defaults to http://localhost:11434
|
||||||
|
return OllamaLLM(model="llama3.1")
|
||||||
|
|
||||||
|
|
||||||
|
def get_vector_store() -> QdrantStore:
|
||||||
|
"""
|
||||||
|
Connect to the local Qdrant instance and load the collection.
|
||||||
|
"""
|
||||||
|
# Qdrant defaults to http://localhost:6333
|
||||||
|
return QdrantStore(
|
||||||
|
url="http://localhost:6333",
|
||||||
|
collection_name="rag_collection",
|
||||||
|
embedding_function=None, # embeddings are already stored
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def build_qa_chain(llm: OllamaLLM, vector_store: QdrantStore) -> RetrievalQA:
|
||||||
|
"""
|
||||||
|
Build a RetrievalQA chain that uses the vector store for context retrieval.
|
||||||
|
"""
|
||||||
|
memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)
|
||||||
|
|
||||||
|
return RetrievalQA.from_chain_type(
|
||||||
|
llm=llm,
|
||||||
|
chain_type="stuff",
|
||||||
|
retriever=vector_store.as_retriever(search_kwargs={"k": 4}),
|
||||||
|
memory=memory,
|
||||||
|
return_source_documents=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
run_cli()
|
"""
|
||||||
|
Main entry point: prompt user for a question and print the answer.
|
||||||
|
"""
|
||||||
|
print("Initializing RAG agent...")
|
||||||
|
try:
|
||||||
|
llm = get_llm()
|
||||||
|
vector_store = get_vector_store()
|
||||||
|
qa_chain = build_qa_chain(llm, vector_store)
|
||||||
|
except Exception as exc:
|
||||||
|
print(f"Failed to initialize components: {exc}")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
print("RAG agent ready. Type your question (or 'exit' to quit).")
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
user_input = input("\n> ").strip()
|
||||||
|
except (EOFError, KeyboardInterrupt):
|
||||||
|
print("\nExiting.")
|
||||||
|
break
|
||||||
|
|
||||||
|
if user_input.lower() in {"exit", "quit"}:
|
||||||
|
print("Goodbye!")
|
||||||
|
break
|
||||||
|
|
||||||
|
if not user_input:
|
||||||
|
print("Please enter a non-empty question.")
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
result = qa_chain({"question": user_input})
|
||||||
|
answer = result.get("answer", "No answer returned.")
|
||||||
|
sources = result.get("source_documents", [])
|
||||||
|
print("\nAnswer:")
|
||||||
|
print(answer)
|
||||||
|
if sources:
|
||||||
|
print("\nSources:")
|
||||||
|
for doc in sources:
|
||||||
|
print(f"- {doc.metadata.get('source', 'unknown')}")
|
||||||
|
except Exception as exc:
|
||||||
|
print(f"Error during query: {exc}")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
Reference in New Issue
Block a user