migrate to uv (#634)

This commit is contained in:
Daniel Chalef 2025-06-27 12:12:49 -07:00 committed by GitHub
parent c29893d972
commit a7ca777af5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 5347 additions and 7055 deletions

View file

@ -9,3 +9,11 @@ updates:
directory: "/" # Location of package manifests
schedule:
interval: "weekly"
- package-ecosystem: "pip"
directory: "/server" # Location of server package manifests
schedule:
interval: "weekly"
- package-ecosystem: "pip"
directory: "/mcp_server" # Location of server package manifests
schedule:
interval: "weekly"

View file

@ -4,9 +4,6 @@ on:
push:
tags: ["v*.*.*"]
env:
POETRY_VERSION: "2.1.2"
jobs:
release:
runs-on: ubuntu-latest
@ -18,21 +15,23 @@ jobs:
url: https://pypi.org/p/zep-cloud
steps:
- uses: actions/checkout@v4
- name: Install poetry
run: pipx install poetry==$POETRY_VERSION
- name: Set up Python 3.10
uses: actions/setup-python@v5
with:
python-version: "3.10"
cache: "poetry"
- name: Install uv
uses: astral-sh/setup-uv@v3
with:
version: "latest"
- name: Compare pyproject version with tag
run: |
TAG_VERSION=${GITHUB_REF#refs/tags/}
if [ "$TAG_VERSION" != "v$(poetry version --short)" ]; then
echo "Tag version $TAG_VERSION does not match the project version $(poetry version --short)"
PROJECT_VERSION=$(uv run python -c "import tomllib; print('v' + tomllib.load(open('pyproject.toml', 'rb'))['project']['version'])")
if [ "$TAG_VERSION" != "$PROJECT_VERSION" ]; then
echo "Tag version $TAG_VERSION does not match the project version $PROJECT_VERSION"
exit 1
fi
- name: Build project for distribution
run: poetry build
run: uv build
- name: Publish package distributions to PyPI
uses: pypa/gh-action-pypi-publish@release/v1

View file

@ -17,20 +17,17 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: Install Poetry
uses: snok/install-poetry@v1
- name: Install uv
uses: astral-sh/setup-uv@v3
with:
version: 2.1.2
virtualenvs-create: true
virtualenvs-in-project: true
installer-parallel: true
version: "latest"
- name: Install dependencies
run: poetry install --no-interaction --with dev
run: uv sync --extra dev
- name: Run MyPy for graphiti-core
shell: bash
run: |
set -o pipefail
poetry run mypy ./graphiti_core --show-column-numbers --show-error-codes | sed -E '
uv run mypy ./graphiti_core --show-column-numbers --show-error-codes | sed -E '
s/^(.*):([0-9]+):([0-9]+): (error|warning): (.+) \[(.+)\]/::error file=\1,line=\2,endLine=\2,col=\3,title=\6::\5/;
s/^(.*):([0-9]+):([0-9]+): note: (.+)/::notice file=\1,line=\2,endLine=\2,col=\3,title=Note::\4/;
'
@ -38,13 +35,13 @@ jobs:
shell: bash
run: |
cd server
poetry install --no-interaction --with dev
uv sync --extra dev
- name: Run MyPy for graph-service
shell: bash
run: |
cd server
set -o pipefail
poetry run mypy . --show-column-numbers --show-error-codes | sed -E '
uv run mypy . --show-column-numbers --show-error-codes | sed -E '
s/^(.*):([0-9]+):([0-9]+): (error|warning): (.+) \[(.+)\]/::error file=\1,line=\2,endLine=\2,col=\3,title=\6::\5/;
s/^(.*):([0-9]+):([0-9]+): note: (.+)/::notice file=\1,line=\2,endLine=\2,col=\3,title=Note::\4/;
'

View file

@ -17,22 +17,14 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: Load cached Poetry installation
uses: actions/cache@v4
- name: Install uv
uses: astral-sh/setup-uv@v3
with:
path: ~/.local
key: poetry-${{ runner.os }}-${{ hashFiles('**/poetry.lock') }}
- name: Install Poetry
uses: snok/install-poetry@v1
with:
version: 2.1.2
virtualenvs-create: true
virtualenvs-in-project: true
installer-parallel: true
version: "latest"
- name: Install dependencies
run: poetry install --no-interaction --no-root
run: uv sync --extra dev
- name: Run non-integration tests
env:
PYTHONPATH: ${{ github.workspace }}
run: |
poetry run pytest -m "not integration"
uv run pytest -m "not integration"

11
.gitignore vendored
View file

@ -95,12 +95,11 @@ ipython_config.py
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# uv
# It is generally recommended to include uv.lock in version control.
# This ensures reproducibility across different environments.
# https://docs.astral.sh/uv/concepts/projects/#lockfile
# uv.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.

View file

@ -20,11 +20,11 @@ For **feature requests**, tell us the story of what you're trying to accomplish.
For **bug reports**, we need enough context to reproduce the problem. Use the [GitHub issue tracker](https://github.com/getzep/graphiti/issues) and include:
- A clear title that summarizes the specific problem
- What you were trying to do when you encountered the bug
- What you expected to happen
- What actually happened
- A code sample or test case that demonstrates the issue
- A clear title that summarizes the specific problem
- What you were trying to do when you encountered the bug
- What you expected to happen
- What actually happened
- A code sample or test case that demonstrates the issue
### Share Your Use Cases
@ -46,78 +46,78 @@ Once you've found an issue tagged with "good first issue" or "help wanted," or p
1. Fork the repository on GitHub.
2. Clone your fork locally:
```
git clone https://github.com/getzep/graphiti
cd graphiti
```
```
git clone https://github.com/getzep/graphiti
cd graphiti
```
3. Set up your development environment:
- Ensure you have Python 3.10+ installed.
- Install Poetry: https://python-poetry.org/docs/#installation
- Install project dependencies:
```
make install
```
- To run integration tests, set the appropriate environment variables
- Ensure you have Python 3.10+ installed.
- Install uv: https://docs.astral.sh/uv/getting-started/installation/
- Install project dependencies:
```
make install
```
- To run integration tests, set the appropriate environment variables
```
export TEST_OPENAI_API_KEY=...
export TEST_OPENAI_MODEL=...
export TEST_ANTHROPIC_API_KEY=...
# For Neo4j
export TEST_URI=neo4j://...
export TEST_USER=...
export TEST_PASSWORD=...
```
```
export TEST_OPENAI_API_KEY=...
export TEST_OPENAI_MODEL=...
export TEST_ANTHROPIC_API_KEY=...
# For Neo4j
export TEST_URI=neo4j://...
export TEST_USER=...
export TEST_PASSWORD=...
```
## Making Changes
1. Create a new branch for your changes:
```
git checkout -b your-branch-name
```
```
git checkout -b your-branch-name
```
2. Make your changes in the codebase.
3. Write or update tests as necessary.
4. Run the tests to ensure they pass:
```
make test
```
```
make test
```
5. Format your code:
```
make format
```
```
make format
```
6. Run linting checks:
```
make lint
```
```
make lint
```
## Submitting Changes
1. Commit your changes:
```
git commit -m "Your detailed commit message"
```
```
git commit -m "Your detailed commit message"
```
2. Push to your fork:
```
git push origin your-branch-name
```
```
git push origin your-branch-name
```
3. Submit a pull request through the GitHub website to https://github.com/getzep/graphiti.
## Pull Request Guidelines
- Provide a clear title and description of your changes.
- Include any relevant issue numbers in the PR description.
- Ensure all tests pass and there are no linting errors.
- Update documentation if you're changing functionality.
- Provide a clear title and description of your changes.
- Include any relevant issue numbers in the PR description.
- Ensure all tests pass and there are no linting errors.
- Update documentation if you're changing functionality.
## Code Style and Quality
We use several tools to maintain code quality:
- Ruff for linting and formatting
- Mypy for static type checking
- Pytest for testing
- Ruff for linting and formatting
- Mypy for static type checking
- Pytest for testing
Before submitting a pull request, please run:

View file

@ -1,43 +1,87 @@
# Build stage
# syntax=docker/dockerfile:1.9
FROM python:3.12-slim as builder
WORKDIR /app
# Install system dependencies
# Install system dependencies for building
RUN apt-get update && apt-get install -y --no-install-recommends \
gcc \
curl \
ca-certificates \
&& rm -rf /var/lib/apt/lists/*
# Install Poetry
RUN pip install --no-cache-dir poetry
# Install uv using the installer script
ADD https://astral.sh/uv/install.sh /uv-installer.sh
RUN sh /uv-installer.sh && rm /uv-installer.sh
ENV PATH="/root/.local/bin:$PATH"
# Copy only the files needed for installation
COPY ./pyproject.toml ./poetry.lock* ./README.md /app/
COPY ./graphiti_core /app/graphiti_core
COPY ./server/pyproject.toml ./server/poetry.lock* /app/server/
# Configure uv for optimal Docker usage
ENV UV_COMPILE_BYTECODE=1 \
UV_LINK_MODE=copy \
UV_PYTHON_DOWNLOADS=never
RUN poetry config virtualenvs.create false
# Copy and build main graphiti-core project
COPY ./pyproject.toml ./README.md ./
COPY ./graphiti_core ./graphiti_core
# Install the local package
RUN poetry build && pip install dist/*.whl
# Build graphiti-core wheel
RUN --mount=type=cache,target=/root/.cache/uv \
uv build
# Install server dependencies
WORKDIR /app/server
RUN poetry install --no-interaction --no-ansi --only main --no-root
# Install the built wheel to make it available for server
RUN --mount=type=cache,target=/root/.cache/uv \
pip install dist/*.whl
# Runtime stage - build the server here
FROM python:3.12-slim
# Copy only the necessary files from the builder stage
COPY --from=builder /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages
COPY --from=builder /usr/local/bin /usr/local/bin
# Install uv using the installer script
RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
ca-certificates \
&& rm -rf /var/lib/apt/lists/*
# Create the app directory and copy server files
ADD https://astral.sh/uv/install.sh /uv-installer.sh
RUN sh /uv-installer.sh && rm /uv-installer.sh
ENV PATH="/root/.local/bin:$PATH"
# Configure uv for runtime
ENV UV_COMPILE_BYTECODE=1 \
UV_LINK_MODE=copy \
UV_PYTHON_DOWNLOADS=never
# Create non-root user
RUN groupadd -r app && useradd -r -d /app -g app app
# Copy graphiti-core wheel from builder
COPY --from=builder /app/dist/*.whl /tmp/
# Install graphiti-core wheel first
RUN --mount=type=cache,target=/root/.cache/uv \
uv pip install --system /tmp/*.whl
# Set up the server application
WORKDIR /app
COPY ./server /app
COPY ./server/pyproject.toml ./server/README.md ./server/uv.lock ./
COPY ./server/graph_service ./graph_service
# Install server dependencies and application
RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --frozen --no-dev
# Change ownership to app user
RUN chown -R app:app /app
# Set environment variables
ENV PYTHONUNBUFFERED=1
ENV PORT=8000
# Command to run the application
ENV PYTHONUNBUFFERED=1 \
PATH="/app/.venv/bin:$PATH"
CMD uvicorn graph_service.main:app --host 0.0.0.0 --port $PORT
# Switch to non-root user
USER app
# Set port
ENV PORT=8000
EXPOSE $PORT
# Use uv run for execution
CMD ["uv", "run", "uvicorn", "graph_service.main:app", "--host", "0.0.0.0", "--port", "8000"]

View file

@ -2,17 +2,17 @@
# Define variables
PYTHON = python3
POETRY = poetry
PYTEST = $(POETRY) run pytest
RUFF = $(POETRY) run ruff
MYPY = $(POETRY) run mypy
UV = uv
PYTEST = $(UV) run pytest
RUFF = $(UV) run ruff
MYPY = $(UV) run mypy
# Default target
all: format lint test
# Install dependencies
install:
$(POETRY) install --with dev
$(UV) sync --extra dev
# Format code
format:

View file

@ -128,7 +128,7 @@ pip install graphiti-core
or
```bash
poetry add graphiti-core
uv add graphiti-core
```
You can also install optional LLM providers as extras:
@ -261,11 +261,11 @@ Graphiti supports Google's Gemini models for both LLM inference and embeddings.
Install Graphiti:
```bash
poetry add "graphiti-core[google-genai]"
uv add "graphiti-core[google-genai]"
# or
uv add "graphiti-core[google-genai]"
pip install "graphiti-core[google-genai]"
```
```python
@ -302,10 +302,9 @@ graphiti = Graphiti(
Graphiti supports Ollama for running local LLMs and embedding models via Ollama's OpenAI-compatible API. This is ideal for privacy-focused applications or when you want to avoid API costs.
Install the models:
ollama pull deepseek-r1:7b # LLM
ollama pull nomic-embed-text # embeddings
ollama pull deepseek-r1:7b # LLM
ollama pull nomic-embed-text # embeddings
```python
from graphiti_core import Graphiti
@ -346,7 +345,6 @@ graphiti = Graphiti(
Ensure Ollama is running (`ollama serve`) and that you have pulled the models you want to use.
## Documentation
- [Guides and API documentation](https://help.getzep.com/graphiti).

View file

@ -1,5 +1,3 @@
version: '3.8'
services:
graph:
image: graphiti-service:${GITHUB_SHA}
@ -38,4 +36,4 @@ services:
retries: 20
start_period: 3s
environment:
- NEO4J_AUTH=${NEO4J_USER}/${NEO4J_PASSWORD}
- NEO4J_AUTH=${NEO4J_USER}/${NEO4J_PASSWORD}

View file

@ -1,5 +1,3 @@
version: "3.8"
services:
graph:
build:
@ -22,21 +20,25 @@ services:
condition: service_healthy
environment:
- OPENAI_API_KEY=${OPENAI_API_KEY}
- NEO4J_URI=bolt://neo4j:${NEO4J_PORT}
- NEO4J_URI=bolt://neo4j:${NEO4J_PORT:-7687}
- NEO4J_USER=${NEO4J_USER}
- NEO4J_PASSWORD=${NEO4J_PASSWORD}
- PORT=8000
neo4j:
image: neo4j:5.26.2
healthcheck:
test: wget "http://localhost:${NEO4J_PORT}" || exit 1
test:
[
"CMD-SHELL",
"wget -qO- http://localhost:${NEO4J_PORT:-7474} || exit 1",
]
interval: 1s
timeout: 10s
retries: 20
retries: 10
start_period: 3s
ports:
- "7474:7474" # HTTP
- "${NEO4J_PORT}:${NEO4J_PORT}" # Bolt
- "${NEO4J_PORT:-7687}:${NEO4J_PORT:-7687}" # Bolt
volumes:
- neo4j_data:/data
environment:

View file

@ -1,28 +1,49 @@
FROM python:3.11-slim
# syntax=docker/dockerfile:1.9
FROM python:3.12-slim
WORKDIR /app
# Install uv for package management
RUN apt-get update && apt-get install -y curl && \
curl -LsSf https://astral.sh/uv/install.sh | sh && \
apt-get clean && rm -rf /var/lib/apt/lists/*
# Install system dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
ca-certificates \
&& rm -rf /var/lib/apt/lists/*
# Install uv using the installer script
ADD https://astral.sh/uv/install.sh /uv-installer.sh
RUN sh /uv-installer.sh && rm /uv-installer.sh
# Add uv to PATH
ENV PATH="/root/.local/bin:${PATH}"
ENV MCP_SERVER_HOST="0.0.0.0"
# Configure uv for optimal Docker usage
ENV UV_COMPILE_BYTECODE=1 \
UV_LINK_MODE=copy \
UV_PYTHON_DOWNLOADS=never \
MCP_SERVER_HOST="0.0.0.0" \
PYTHONUNBUFFERED=1
# Copy pyproject.toml and install dependencies
COPY pyproject.toml .
RUN uv sync
# Create non-root user
RUN groupadd -r app && useradd -r -d /app -g app app
# Copy project files for dependency installation (better caching)
COPY pyproject.toml uv.lock ./
# Install dependencies first (better layer caching)
RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --frozen --no-dev
# Copy application code
COPY graphiti_mcp_server.py .
COPY graphiti_mcp_server.py ./
# Change ownership to app user
RUN chown -R app:app /app
# Switch to non-root user
USER app
# Expose port
EXPOSE 8000
# Set environment variables
ENV PYTHONUNBUFFERED=1
# Command to run the application
CMD ["uv", "run", "graphiti_mcp_server.py"]

5410
poetry.lock generated

File diff suppressed because it is too large Load diff

View file

@ -10,7 +10,6 @@ authors = [
readme = "README.md"
license = "Apache-2.0"
requires-python = ">=3.10,<4"
packages = [{ include = "graphiti_core", from = "." }]
dependencies = [
"pydantic>=2.11.5",
"neo4j>=5.26.0",
@ -29,34 +28,31 @@ Repository = "https://github.com/getzep/graphiti"
anthropic = ["anthropic>=0.49.0"]
groq = ["groq>=0.2.0"]
google-genai = ["google-genai>=1.8.0"]
falkord-db = ["falkordb (>=1.1.2,<2.0.0)"]
[tool.poetry.group.dev.dependencies]
mypy = ">=1.11.1"
groq = ">=0.2.0"
anthropic = ">=0.49.0"
google-genai = ">=1.8.0"
ipykernel = ">=6.29.5"
jupyterlab = ">=4.2.4"
diskcache-stubs = ">=5.6.3.6.20240818"
langgraph = ">=0.2.15"
langchain-anthropic = ">=0.2.4"
langsmith = ">=0.1.108"
langchain-openai = ">=0.2.6"
sentence-transformers = ">=3.2.1"
transformers = ">=4.45.2"
voyageai = ">=0.2.3"
pytest = ">=8.3.3"
pytest-asyncio = ">=0.24.0"
pytest-xdist = ">=3.6.1"
ruff = ">=0.7.1"
falkord-db = ["falkordb>=1.1.2,<2.0.0"]
dev = [
"mypy>=1.11.1",
"groq>=0.2.0",
"anthropic>=0.49.0",
"google-genai>=1.8.0",
"ipykernel>=6.29.5",
"jupyterlab>=4.2.4",
"diskcache-stubs>=5.6.3.6.20240818",
"langgraph>=0.2.15",
"langchain-anthropic>=0.2.4",
"langsmith>=0.1.108",
"langchain-openai>=0.2.6",
"sentence-transformers>=3.2.1",
"transformers>=4.45.2",
"voyageai>=0.2.3",
"pytest>=8.3.3",
"pytest-asyncio>=0.24.0",
"pytest-xdist>=3.6.1",
"ruff>=0.7.1",
]
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
[tool.poetry]
requires-poetry = ">=2.0"
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.pytest.ini_options]
pythonpath = ["."]
@ -86,8 +82,13 @@ quote-style = "single"
indent-style = "space"
docstring-code-format = true
[mypy-falkordb]
[tool.mypy]
packages = ["graphiti_core"]
[[tool.mypy.overrides]]
module = "falkordb"
ignore_missing_imports = true
[mypy-falkordb.asyncio]
[[tool.mypy.overrides]]
module = "falkordb.asyncio"
ignore_missing_imports = true

View file

@ -2,17 +2,17 @@
# Define variables
PYTHON = python3
POETRY = poetry
PYTEST = $(POETRY) run pytest
RUFF = $(POETRY) run ruff
MYPY = $(POETRY) run mypy
UV = uv
PYTEST = $(UV) run pytest
RUFF = $(UV) run ruff
MYPY = $(UV) run mypy
# Default target
all: format lint test
# Install dependencies
install:
$(POETRY) install --with dev
$(UV) sync --extra dev
# Format code
format:

1442
server/poetry.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,33 +1,38 @@
[tool.poetry]
[project]
name = "graph-service"
version = "0.1.0"
description = "Zep Graph service implementing Graphiti package"
authors = ["Paul Paliychuk <paul@getzep.com>"]
authors = [
{ "name" = "Paul Paliychuk", "email" = "paul@getzep.com" },
]
readme = "README.md"
packages = [{ include = "graph_service" }]
requires-python = ">=3.10"
dependencies = [
"fastapi>=0.115.0",
"graphiti-core",
"pydantic-settings>=2.4.0",
"uvicorn>=0.30.6",
"httpx>=0.28.1",
]
[tool.poetry.dependencies]
python = "^3.10"
fastapi = "^0.115.0"
graphiti-core = { path = "../" }
pydantic-settings = "^2.4.0"
uvicorn = "^0.30.6"
httpx = "^0.28.1"
[tool.poetry.group.dev.dependencies]
pydantic = "^2.8.2"
mypy = "^1.11.1"
pytest = "^8.3.2"
python-dotenv = "^1.0.1"
pytest-asyncio = "^0.24.0"
pytest-xdist = "^3.6.1"
ruff = "^0.6.2"
fastapi-cli = "^0.0.5"
[project.optional-dependencies]
dev = [
"pydantic>=2.8.2",
"mypy>=1.11.1",
"pytest>=8.3.2",
"python-dotenv>=1.0.1",
"pytest-asyncio>=0.24.0",
"pytest-xdist>=3.6.1",
"ruff>=0.6.2",
"fastapi-cli>=0.0.5",
]
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.hatch.build.targets.wheel]
packages = ["graph_service"]
[tool.pytest.ini_options]
pythonpath = ["."]

1159
server/uv.lock generated Normal file

File diff suppressed because it is too large Load diff

3921
uv.lock generated Normal file

File diff suppressed because it is too large Load diff