Skip to content

Commit 1d49ef2

Browse files
authored
[Runtime] Reduce dependency to speed up CI and reduce image size (#3195)
* reduce dependency for runtime * try making llama-index an optional dependency that's not installed by default * do not install llama-index in CI * do not install llama-index in the app docker as well
1 parent 938ed02 commit 1d49ef2

File tree

9 files changed

+110
-100
lines changed

9 files changed

+110
-100
lines changed

.github/workflows/dummy-agent-test.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ jobs:
2525
- name: Set up environment
2626
run: |
2727
curl -sSL https://install.python-poetry.org | python3 -
28-
poetry install --without evaluation
28+
poetry install --without evaluation,llama-index
2929
poetry run playwright install --with-deps chromium
3030
wget https://huggingface.co/BAAI/bge-small-en-v1.5/raw/main/1_Pooling/config.json -P /tmp/llama_index/models--BAAI--bge-small-en-v1.5/snapshots/5c38ec7c405ec4b44b94cc5a9bb96e735b38267a/1_Pooling/
3131
- name: Run tests

.github/workflows/review-pr.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ jobs:
5050
run: |
5151
curl -sSL https://install.python-poetry.org | python3 -
5252
export PATH="/github/home/.local/bin:$PATH"
53-
poetry install --without evaluation
53+
poetry install --without evaluation,llama-index
5454
poetry run playwright install --with-deps chromium
5555
5656
- name: Run OpenDevin

.github/workflows/run-unit-tests.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ jobs:
7070
cache: "poetry"
7171

7272
- name: Install Python dependencies using Poetry
73-
run: poetry install
73+
run: poetry install --without evaluation,llama-index
7474

7575
- name: Install & Start Docker
7676
if: env.INSTALL_DOCKER == '1'
@@ -153,7 +153,7 @@ jobs:
153153
cache: "poetry"
154154

155155
- name: Install Python dependencies using Poetry
156-
run: poetry install --without evaluation
156+
run: poetry install --without evaluation,llama-index
157157

158158
- name: Build Environment
159159
run: make build

.github/workflows/solve-issue.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ jobs:
4040
run: |
4141
curl -sSL https://install.python-poetry.org | python3 -
4242
export PATH="/github/home/.local/bin:$PATH"
43-
poetry install --without evaluation
43+
poetry install --without evaluation,llama-index
4444
poetry run playwright install --with-deps chromium
4545
4646

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ install-python-dependencies:
141141
export HNSWLIB_NO_NATIVE=1; \
142142
poetry run pip install chroma-hnswlib; \
143143
fi
144-
@poetry install
144+
@poetry install --without llama-index
145145
@if [ -f "/etc/manjaro-release" ]; then \
146146
echo "$(BLUE)Detected Manjaro Linux. Installing Playwright dependencies...$(RESET)"; \
147147
poetry run pip install playwright; \

containers/app/Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ RUN apt-get update -y \
2626

2727
COPY ./pyproject.toml ./poetry.lock ./
2828
RUN touch README.md
29-
RUN export POETRY_CACHE_DIR && poetry install --without evaluation --no-root && rm -rf $POETRY_CACHE_DIR
29+
RUN export POETRY_CACHE_DIR && poetry install --without evaluation,llama-index --no-root && rm -rf $POETRY_CACHE_DIR
3030

3131
FROM python:3.12.3-slim AS runtime
3232

opendevin/memory/memory.py

+101-92
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
11
import threading
22

3-
import chromadb
4-
import llama_index.embeddings.openai.base as llama_openai
5-
from llama_index.core import Document, VectorStoreIndex
6-
from llama_index.core.retrievers import VectorIndexRetriever
7-
from llama_index.vector_stores.chroma import ChromaVectorStore
83
from openai._exceptions import APIConnectionError, InternalServerError, RateLimitError
94
from tenacity import (
105
retry,
@@ -17,101 +12,115 @@
1712
from opendevin.core.logger import opendevin_logger as logger
1813
from opendevin.core.utils import json
1914

20-
# TODO: this could be made configurable
21-
num_retries: int = 10
22-
retry_min_wait: int = 3
23-
retry_max_wait: int = 300
24-
25-
# llama-index includes a retry decorator around openai.get_embeddings() function
26-
# it is initialized with hard-coded values and errors
27-
# this non-customizable behavior is creating issues when it's retrying faster than providers' rate limits
28-
# this block attempts to banish it and replace it with our decorator, to allow users to set their own limits
29-
30-
if hasattr(llama_openai.get_embeddings, '__wrapped__'):
31-
original_get_embeddings = llama_openai.get_embeddings.__wrapped__
32-
else:
33-
logger.warning('Cannot set custom retry limits.')
34-
num_retries = 1
35-
original_get_embeddings = llama_openai.get_embeddings
36-
37-
38-
def attempt_on_error(retry_state):
39-
logger.error(
40-
f'{retry_state.outcome.exception()}. Attempt #{retry_state.attempt_number} | You can customize these settings in the configuration.',
41-
exc_info=False,
15+
try:
16+
import chromadb
17+
import llama_index.embeddings.openai.base as llama_openai
18+
from llama_index.core import Document, VectorStoreIndex
19+
from llama_index.core.retrievers import VectorIndexRetriever
20+
from llama_index.vector_stores.chroma import ChromaVectorStore
21+
22+
LLAMA_INDEX_AVAILABLE = True
23+
except ImportError:
24+
LLAMA_INDEX_AVAILABLE = False
25+
26+
if LLAMA_INDEX_AVAILABLE:
27+
# TODO: this could be made configurable
28+
num_retries: int = 10
29+
retry_min_wait: int = 3
30+
retry_max_wait: int = 300
31+
32+
# llama-index includes a retry decorator around openai.get_embeddings() function
33+
# it is initialized with hard-coded values and errors
34+
# this non-customizable behavior is creating issues when it's retrying faster than providers' rate limits
35+
# this block attempts to banish it and replace it with our decorator, to allow users to set their own limits
36+
37+
if hasattr(llama_openai.get_embeddings, '__wrapped__'):
38+
original_get_embeddings = llama_openai.get_embeddings.__wrapped__
39+
else:
40+
logger.warning('Cannot set custom retry limits.')
41+
num_retries = 1
42+
original_get_embeddings = llama_openai.get_embeddings
43+
44+
def attempt_on_error(retry_state):
45+
logger.error(
46+
f'{retry_state.outcome.exception()}. Attempt #{retry_state.attempt_number} | You can customize these settings in the configuration.',
47+
exc_info=False,
48+
)
49+
return None
50+
51+
@retry(
52+
reraise=True,
53+
stop=stop_after_attempt(num_retries),
54+
wait=wait_random_exponential(min=retry_min_wait, max=retry_max_wait),
55+
retry=retry_if_exception_type(
56+
(RateLimitError, APIConnectionError, InternalServerError)
57+
),
58+
after=attempt_on_error,
4259
)
43-
return None
44-
45-
46-
@retry(
47-
reraise=True,
48-
stop=stop_after_attempt(num_retries),
49-
wait=wait_random_exponential(min=retry_min_wait, max=retry_max_wait),
50-
retry=retry_if_exception_type(
51-
(RateLimitError, APIConnectionError, InternalServerError)
52-
),
53-
after=attempt_on_error,
54-
)
55-
def wrapper_get_embeddings(*args, **kwargs):
56-
return original_get_embeddings(*args, **kwargs)
57-
58-
59-
llama_openai.get_embeddings = wrapper_get_embeddings
60-
61-
62-
class EmbeddingsLoader:
63-
"""Loader for embedding model initialization."""
64-
65-
@staticmethod
66-
def get_embedding_model(strategy: str, llm_config: LLMConfig):
67-
supported_ollama_embed_models = [
68-
'llama2',
69-
'mxbai-embed-large',
70-
'nomic-embed-text',
71-
'all-minilm',
72-
'stable-code',
73-
]
74-
if strategy in supported_ollama_embed_models:
75-
from llama_index.embeddings.ollama import OllamaEmbedding
76-
77-
return OllamaEmbedding(
78-
model_name=strategy,
79-
base_url=llm_config.embedding_base_url,
80-
ollama_additional_kwargs={'mirostat': 0},
81-
)
82-
elif strategy == 'openai':
83-
from llama_index.embeddings.openai import OpenAIEmbedding
84-
85-
return OpenAIEmbedding(
86-
model='text-embedding-ada-002',
87-
api_key=llm_config.api_key,
88-
)
89-
elif strategy == 'azureopenai':
90-
from llama_index.embeddings.azure_openai import AzureOpenAIEmbedding
91-
92-
return AzureOpenAIEmbedding(
93-
model='text-embedding-ada-002',
94-
deployment_name=llm_config.embedding_deployment_name,
95-
api_key=llm_config.api_key,
96-
azure_endpoint=llm_config.base_url,
97-
api_version=llm_config.api_version,
98-
)
99-
elif (strategy is not None) and (strategy.lower() == 'none'):
100-
# TODO: this works but is not elegant enough. The incentive is when
101-
# an agent using embeddings is not used, there is no reason we need to
102-
# initialize an embedding model
103-
return None
104-
else:
105-
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
106-
107-
return HuggingFaceEmbedding(model_name='BAAI/bge-small-en-v1.5')
60+
def wrapper_get_embeddings(*args, **kwargs):
61+
return original_get_embeddings(*args, **kwargs)
62+
63+
llama_openai.get_embeddings = wrapper_get_embeddings
64+
65+
class EmbeddingsLoader:
66+
"""Loader for embedding model initialization."""
67+
68+
@staticmethod
69+
def get_embedding_model(strategy: str, llm_config: LLMConfig):
70+
supported_ollama_embed_models = [
71+
'llama2',
72+
'mxbai-embed-large',
73+
'nomic-embed-text',
74+
'all-minilm',
75+
'stable-code',
76+
]
77+
if strategy in supported_ollama_embed_models:
78+
from llama_index.embeddings.ollama import OllamaEmbedding
79+
80+
return OllamaEmbedding(
81+
model_name=strategy,
82+
base_url=llm_config.embedding_base_url,
83+
ollama_additional_kwargs={'mirostat': 0},
84+
)
85+
elif strategy == 'openai':
86+
from llama_index.embeddings.openai import OpenAIEmbedding
87+
88+
return OpenAIEmbedding(
89+
model='text-embedding-ada-002',
90+
api_key=llm_config.api_key,
91+
)
92+
elif strategy == 'azureopenai':
93+
from llama_index.embeddings.azure_openai import AzureOpenAIEmbedding
94+
95+
return AzureOpenAIEmbedding(
96+
model='text-embedding-ada-002',
97+
deployment_name=llm_config.embedding_deployment_name,
98+
api_key=llm_config.api_key,
99+
azure_endpoint=llm_config.base_url,
100+
api_version=llm_config.api_version,
101+
)
102+
elif (strategy is not None) and (strategy.lower() == 'none'):
103+
# TODO: this works but is not elegant enough. The incentive is when
104+
# an agent using embeddings is not used, there is no reason we need to
105+
# initialize an embedding model
106+
return None
107+
else:
108+
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
109+
110+
return HuggingFaceEmbedding(model_name='BAAI/bge-small-en-v1.5')
108111

109112

110113
class LongTermMemory:
111114
"""Handles storing information for the agent to access later, using chromadb."""
112115

113116
def __init__(self, llm_config: LLMConfig, memory_max_threads: int = 1):
114117
"""Initialize the chromadb and set up ChromaVectorStore for later use."""
118+
if not LLAMA_INDEX_AVAILABLE:
119+
raise ImportError(
120+
'llama_index and its dependencies are not installed. '
121+
'To use LongTermMemory, please run: poetry install --with llama-index'
122+
)
123+
115124
db = chromadb.Client(chromadb.Settings(anonymized_telemetry=False))
116125
self.collection = db.get_or_create_collection(name='memories')
117126
vector_store = ChromaVectorStore(chroma_collection=self.collection)

opendevin/runtime/utils/runtime_templates/Dockerfile.j2

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ RUN mv /opendevin/{{ source_code_dirname }} /opendevin/code
5656
# 3. Clear poetry, apt, mamba caches
5757
RUN cd /opendevin/code && \
5858
/opendevin/miniforge3/bin/mamba run -n base poetry env use python3.11 && \
59-
/opendevin/miniforge3/bin/mamba run -n base poetry install --no-interaction --no-root && \
59+
/opendevin/miniforge3/bin/mamba run -n base poetry install --only main,runtime --no-interaction --no-root && \
6060
apt-get update && \
6161
/opendevin/miniforge3/bin/mamba run -n base poetry run pip install playwright && \
6262
/opendevin/miniforge3/bin/mamba run -n base poetry run playwright install --with-deps chromium && \

pyproject.toml

+1
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ python-pptx = "*"
8585
pylatexenc = "*"
8686
opencv-python = "*"
8787

88+
8889
[build-system]
8990
build-backend = "poetry.core.masonry.api"
9091
requires = [

0 commit comments

Comments
 (0)