Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[run]
source = chatbot_api/src, chatbot_frontend/src, hospital_neo4j_etl/src
omit =
*/tests/*
*/test_*
*/__init__.py
*/conftest.py
*/migrations/*
*/venv/*
*/.venv/*

[report]
exclude_lines =
pragma: no cover
def __repr__
if self.debug:
if settings.DEBUG
raise AssertionError
raise NotImplementedError
if 0:
if __name__ == .__main__.:
class .*\bProtocol\):
@(abc\.)?abstractmethod

[html]
directory = htmlcov
142 changes: 142 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
name: CI

on:
push:
branches: [master, main]
pull_request:
branches: [master, main]

jobs:
code-quality:
name: Code Quality
runs-on: ubuntu-latest
if: ${{ !contains(github.event.head_commit.message, '[skip ci]') }}

steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Install uv
uses: astral-sh/setup-uv@v3
with:
enable-cache: true
cache-dependency-glob: "**/pyproject.toml"

- name: Set up Python 3.11
run: uv python install 3.11

- name: Create virtual environment and install dependencies
run: |
uv venv --python 3.11
uv pip install -e "chatbot_api[dev]" -e "chatbot_frontend[dev]" -e "hospital_neo4j_etl[dev]"

- name: Run linting and formatting checks
run: |
uv run ruff check chatbot_api/src/ chatbot_frontend/src/ hospital_neo4j_etl/src/ tests/
uv run ruff format --check chatbot_api/src/ chatbot_frontend/src/ hospital_neo4j_etl/src/ tests/

- name: Run type checking
run: uv run mypy chatbot_api/src/

unit-tests:
name: Unit Tests (Python ${{ matrix.python-version }})
runs-on: ubuntu-latest
if: ${{ !contains(github.event.head_commit.message, '[skip ci]') }}
strategy:
matrix:
python-version: ["3.9", "3.11"]

steps:
- uses: actions/checkout@v4

- name: Install uv
uses: astral-sh/setup-uv@v3
with:
enable-cache: true
cache-dependency-glob: "**/pyproject.toml"

- name: Set up Python ${{ matrix.python-version }}
run: uv python install ${{ matrix.python-version }}

- name: Create virtual environment and install dependencies
run: |
uv venv --python ${{ matrix.python-version }}
uv pip install -e "chatbot_api[dev]" -e "chatbot_frontend[dev]" -e "hospital_neo4j_etl[dev]"

- name: Run unit tests with coverage
run: make test-unit

integration-tests:
name: Integration Tests (Python ${{ matrix.python-version }})
runs-on: ubuntu-latest
if: ${{ !contains(github.event.head_commit.message, '[skip ci]') }}
strategy:
matrix:
python-version: ["3.9", "3.11"]

steps:
- uses: actions/checkout@v4

- name: Install uv
uses: astral-sh/setup-uv@v3
with:
enable-cache: true
cache-dependency-glob: "**/pyproject.toml"

- name: Set up Python ${{ matrix.python-version }}
run: uv python install ${{ matrix.python-version }}

- name: Create virtual environment and install dependencies
run: |
uv venv --python ${{ matrix.python-version }}
uv pip install -e "chatbot_api[dev]" -e "chatbot_frontend[dev]" -e "hospital_neo4j_etl[dev]"

- name: Run integration tests with coverage
run: |
uv run pytest tests/integration/ -v --cov=chatbot_api/src --cov=chatbot_frontend/src --cov=hospital_neo4j_etl/src

- name: Upload coverage to Codecov
if: matrix.python-version == '3.11' # Only upload once
uses: codecov/codecov-action@v3
with:
file: ./coverage.xml
fail_ci_if_error: false

build-validation:
name: Docker Build Validation
runs-on: ubuntu-latest
if: ${{ contains(github.event.head_commit.message, 'docker') || contains(github.event.head_commit.message, 'Docker') || github.event_name == 'pull_request' }}
steps:
- uses: actions/checkout@v4

- name: Check for Docker-related changes
uses: dorny/paths-filter@v2
id: docker-changes
with:
filters: |
docker:
- 'docker-compose.yml'
- '**/Dockerfile'
- '.dockerignore'

- name: Create dummy .env file for Docker build
if: steps.docker-changes.outputs.docker == 'true' || github.event_name == 'pull_request'
run: |
cat > .env << 'EOF'
# Dummy environment variables for CI build validation
OPENAI_API_KEY=sk-dummy-key-for-ci-build-only
NEO4J_URI=neo4j://localhost:7687
NEO4J_USERNAME=neo4j
NEO4J_PASSWORD=password
HOSPITAL_AGENT_MODEL=gpt-3.5-turbo
HOSPITAL_CYPHER_MODEL=gpt-3.5-turbo
HOSPITAL_QA_MODEL=gpt-3.5-turbo
CHATBOT_URL=http://localhost:8000/hospital-rag-agent
EOF

- name: Validate Docker Compose build
if: steps.docker-changes.outputs.docker == 'true' || github.event_name == 'pull_request'
run: |
docker compose build --no-cache
docker compose config --quiet
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,6 @@ __pycache__
*.pyc
.DS_Store

*.egg-info
*.coverage
htmlcov/
23 changes: 23 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.1.8
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix]
- id: ruff-format

- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.8.0
hooks:
- id: mypy
additional_dependencies: [types-requests]
args: [--ignore-missing-imports, --explicit-package-bases]
files: ^chatbot_api/

- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
23 changes: 22 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,29 @@ start:
stop:
docker compose down chatbot_api chatbot_frontend

format:
test:
uv run pytest tests/ -v --cov=chatbot_api/src --cov=chatbot_frontend/src --cov=hospital_neo4j_etl/src --ignore=tests/performance

test-unit:
uv run pytest tests/unit/ -v

test-integration:
uv run pytest tests/integration/ -v

format:
uv run ruff format chatbot_api/src/ chatbot_frontend/src/ hospital_neo4j_etl/src/ tests/

lint:
uv run ruff check chatbot_api/src/ chatbot_frontend/src/ hospital_neo4j_etl/src/ tests/

format-check:
uv run ruff format --check chatbot_api/src/ chatbot_frontend/src/ hospital_neo4j_etl/src/ tests/

lint-fix:
uv run ruff check --fix chatbot_api/src/ chatbot_frontend/src/ hospital_neo4j_etl/src/ tests/

pre-commit:
uv run pre-commit run --all-files

install-dev:
uv pip install -e "chatbot_api[dev]" -e "chatbot_frontend[dev]" -e "hospital_neo4j_etl[dev]"
22 changes: 14 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Healthcare RAG Agent
# Healthcare RAG Agent

[![Python](https://img.shields.io/badge/Python-3.8+-blue.svg)](https://www.python.org/)
[![CI](https://github.com/asanmateu/medgraph-ai/workflows/CI/badge.svg)](https://github.com/asanmateu/medgraph-ai/actions)
[![codecov](https://codecov.io/gh/asanmateu/medgraph-ai/branch/master/graph/badge.svg)](https://codecov.io/gh/asanmateu/medgraph-ai)
[![Python](https://img.shields.io/badge/Python-3.9%20|%203.11-blue.svg)](https://www.python.org/)
[![LangChain](https://img.shields.io/badge/LangChain-Latest-green.svg)](https://langchain.com/)
[![Neo4j](https://img.shields.io/badge/Neo4j-5.0+-blue.svg)](https://neo4j.com/)
[![Docker](https://img.shields.io/badge/Docker-Required-blue.svg)](https://www.docker.com/)
Expand All @@ -16,6 +18,7 @@ A Retrieval-Augmented Generation (RAG) agent designed for healthcare information
- [Example Queries](#-example-queries)
- [Database Design](#database-design)
- [Technical Stack](#technical-stack)
- [Contributing](#-contributing)
- [Acknowledgments](#acknowledgments)

## 🎯 Overview
Expand All @@ -24,10 +27,10 @@ This project implements a healthcare-focused RAG chatbot that leverages LangChai

## ✨ Key Features

✅ **Knowledge Graph Integration** - Neo4j for healthcare data relationships
✅ **RESTful API** - FastAPI-powered scalable backend
✅ **Interactive UI** - Intuitive Streamlit interface
✅ **Containerized** - Docker-based deployment
✅ **Knowledge Graph Integration** - Neo4j for healthcare data relationships
✅ **RESTful API** - FastAPI-powered scalable backend
✅ **Interactive UI** - Intuitive Streamlit interface
✅ **Containerized** - Docker-based deployment
✅ **Multi-Model Support** - Configurable OpenAI models

<a name="architecture"></a>
Expand Down Expand Up @@ -147,7 +150,10 @@ Relationships between nodes contain additional contextual information:
- **Docker**: Containerization platform
- **OpenAI GPT-3.5**: Language model for natural language understanding

## Acknowledgments
## 🤝 Contributing

This project builds upon the excellent foundation provided by Real Python's LLM RAG Chatbot [tutorial](https://realpython.com/build-llm-rag-chatbot-with-langchain).
Contributions are welcome. Please ensure that any pull requests maintain the existing code style and include appropriate tests and documentation updates.

## 🙏 Acknowledgments

This project builds upon the excellent foundation provided by Real Python's LLM RAG Chatbot [tutorial](https://realpython.com/build-llm-rag-chatbot-with-langchain).
41 changes: 41 additions & 0 deletions chatbot_api/mypy.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
[mypy]
python_version = 3.9
warn_return_any = True
warn_unused_configs = True
disallow_untyped_defs = False
disallow_incomplete_defs = False
check_untyped_defs = True
disallow_untyped_decorators = False
no_implicit_optional = True
warn_redundant_casts = True
warn_unused_ignores = True
warn_no_return = True
warn_unreachable = True
strict_equality = True
namespace_packages = True
explicit_package_bases = True

# Ignore missing imports for third-party libraries
[mypy-langchain.*]
ignore_missing_imports = True

[mypy-langchain_openai.*]
ignore_missing_imports = True

[mypy-langchain_community.*]
ignore_missing_imports = True

[mypy-neo4j.*]
ignore_missing_imports = True

[mypy-openai.*]
ignore_missing_imports = True

[mypy-pydantic.*]
ignore_missing_imports = True

[mypy-fastapi.*]
ignore_missing_imports = True

[mypy-uvicorn.*]
ignore_missing_imports = True
11 changes: 10 additions & 1 deletion chatbot_api/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,13 @@ dependencies = [
]

[project.optional-dependencies]
dev = ["black", "flake8"]
dev = [
"ruff",
"mypy",
"pre-commit",
"pytest>=7.0.0",
"pytest-asyncio>=0.21.0",
"pytest-mock>=3.10.0",
"httpx>=0.24.0",
"pytest-cov>=4.0.0"
]
12 changes: 7 additions & 5 deletions chatbot_api/src/agents/hospital_rag_agent.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
import os
from typing import List, Optional
from langchain_openai import ChatOpenAI
from langchain.agents import (
create_openai_functions_agent,
Tool,
AgentExecutor,
)
from langchain import hub
from langchain.schema import BasePromptTemplate
from chains.hospital_review_chain import reviews_vector_chain
from chains.hospital_cypher_chain import hospital_cypher_chain
from tools.wait_times import (
get_current_wait_times,
get_most_available_hospital,
)

HOSPITAL_AGENT_MODEL = os.getenv("HOSPITAL_AGENT_MODEL")
HOSPITAL_AGENT_MODEL: Optional[str] = os.getenv("HOSPITAL_AGENT_MODEL")

hospital_agent_prompt = hub.pull("hwchase17/openai-functions-agent")
hospital_agent_prompt: BasePromptTemplate = hub.pull("hwchase17/openai-functions-agent")


tools = [
tools: List[Tool] = [
Tool(
name="Experiences",
func=reviews_vector_chain.invoke,
Expand Down Expand Up @@ -68,7 +70,7 @@
]


chat_model = ChatOpenAI(
chat_model: ChatOpenAI = ChatOpenAI(
model=HOSPITAL_AGENT_MODEL,
temperature=0,
)
Expand All @@ -79,7 +81,7 @@
tools=tools,
)

hospital_rag_agent_executor = AgentExecutor(
hospital_rag_agent_executor: AgentExecutor = AgentExecutor(
agent=hospital_rag_agent,
tools=tools,
return_intermediate_steps=True,
Expand Down
Loading
Loading