Compare commits

...

2 Commits

Author SHA1 Message Date
Adrian Lyjak fd5293ec99 Bump 2025-09-18 10:51:07 -04:00
Adrian Lyjak 42089b6334 Support creating indexes in a specified project_id 2025-09-18 10:50:24 -04:00
6 changed files with 162 additions and 21 deletions
+1 -1
View File
@@ -29,7 +29,7 @@ repos:
- id: black-jupyter
name: black-src
alias: black
exclude: ".*uv.lock"
exclude: ".*uv.lock|examples/extract/solar_panel_e2e_comparison.ipynb"
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.0.1
hooks:
+14 -12
View File
@@ -489,6 +489,7 @@ class LlamaCloudIndex(BaseManagedIndex):
name: str,
project_name: str = DEFAULT_PROJECT_NAME,
organization_id: Optional[str] = None,
project_id: Optional[str] = None,
api_key: Optional[str] = None,
base_url: Optional[str] = None,
app_url: Optional[str] = None,
@@ -504,15 +505,15 @@ class LlamaCloudIndex(BaseManagedIndex):
app_url = app_url or os.environ.get("LLAMA_CLOUD_APP_URL", DEFAULT_APP_URL)
client = get_client(api_key, base_url, app_url, timeout)
# create project if it doesn't exist
project = client.projects.upsert_project(
organization_id=organization_id, request=ProjectCreate(name=project_name)
)
if project.id is None:
raise ValueError(f"Failed to create/get project {project_name}")
if verbose:
print(f"Created project {project.id} with name {project.name}")
if project_id is None:
# create project if it doesn't exist
project = client.projects.upsert_project(
organization_id=organization_id,
request=ProjectCreate(name=project_name),
)
project_id = project.id
if verbose:
print(f"Created project {project_id} with name {project_name}")
# create pipeline
pipeline_create = PipelineCreate(
@@ -523,7 +524,7 @@ class LlamaCloudIndex(BaseManagedIndex):
llama_parse_parameters=llama_parse_parameters or LlamaParseParameters(),
)
pipeline = client.pipelines.upsert_pipeline(
project_id=project.id, request=pipeline_create
project_id=project_id, request=pipeline_create
)
if pipeline.id is None:
raise ValueError(f"Failed to create/get pipeline {name}")
@@ -532,8 +533,7 @@ class LlamaCloudIndex(BaseManagedIndex):
return cls(
name,
project_name=project.name,
organization_id=project.organization_id,
project_id=project_id,
api_key=api_key,
base_url=base_url,
app_url=app_url,
@@ -606,6 +606,7 @@ class LlamaCloudIndex(BaseManagedIndex):
name: str,
project_name: str = DEFAULT_PROJECT_NAME,
organization_id: Optional[str] = None,
project_id: Optional[str] = None,
api_key: Optional[str] = None,
base_url: Optional[str] = None,
app_url: Optional[str] = None,
@@ -631,6 +632,7 @@ class LlamaCloudIndex(BaseManagedIndex):
verbose=verbose,
embedding_config=embedding_config,
transform_config=transform_config,
project_id=project_id,
)
app_url = app_url or os.environ.get("LLAMA_CLOUD_APP_URL", DEFAULT_APP_URL)
+2 -2
View File
@@ -11,13 +11,13 @@ dev = [
[project]
name = "llama-parse"
version = "0.6.67"
version = "0.6.68"
description = "Parse files into RAG-Optimized formats."
authors = [{name = "Logan Markewich", email = "logan@llamaindex.ai"}]
requires-python = ">=3.9,<4.0"
readme = "README.md"
license = "MIT"
dependencies = ["llama-cloud-services>=0.6.67"]
dependencies = ["llama-cloud-services>=0.6.68"]
[project.scripts]
llama-parse = "llama_parse.cli.main:parse"
+1 -1
View File
@@ -19,7 +19,7 @@ dev = [
[project]
name = "llama-cloud-services"
version = "0.6.67"
version = "0.6.68"
description = "Tailored SDK clients for LlamaCloud services."
authors = [{name = "Logan Markewich", email = "logan@runllama.ai"}]
requires-python = ">=3.9,<4.0"
+143 -4
View File
@@ -1,16 +1,155 @@
import pytest
from unittest.mock import MagicMock, patch
import llama_cloud_services.index.base as base
from llama_cloud import (
PipelineEmbeddingConfig_ManagedOpenaiEmbedding,
Project,
Pipeline,
CloudDocument,
)
from llama_index.core.constants import DEFAULT_PROJECT_NAME
from llama_index.core.indices.managed.base import BaseManagedIndex
from llama_cloud_services.index import (
LlamaCloudIndex,
from llama_index.core.schema import Document
from llama_cloud_services.index import LlamaCloudIndex
# Simple test data as values, not fixtures
TEST_PROJECT = Project(id="proj-123", name="test-project", organization_id="org-123")
EMBEDDING_CONFIG = PipelineEmbeddingConfig_ManagedOpenaiEmbedding(
type="MANAGED_OPENAI_EMBEDDING"
)
TEST_PIPELINE = Pipeline(
id="pipe-456",
name="test-pipeline",
project_id="proj-123",
embedding_config=PipelineEmbeddingConfig_ManagedOpenaiEmbedding(
type="MANAGED_OPENAI_EMBEDDING"
),
)
def test_class():
@pytest.fixture
def mock_client() -> MagicMock:
"""Mock client with sensible defaults."""
client = MagicMock()
client.projects.upsert_project.return_value = Project(
id="default-proj", name=DEFAULT_PROJECT_NAME, organization_id="default-org"
)
client.pipelines.upsert_pipeline.return_value = Pipeline(
id="default-pipe",
name="default",
project_id="default-proj",
embedding_config=EMBEDDING_CONFIG,
)
client.pipelines.upsert_batch_pipeline_documents.return_value = [
CloudDocument(id="doc-1", text="test", metadata={})
]
return client
@pytest.fixture(autouse=True)
def base_patches(mock_client: MagicMock) -> None:
"""Auto-applied patches for all tests."""
with (
patch.object(base, "get_client", return_value=mock_client),
patch.object(
base,
"resolve_project_and_pipeline",
return_value=(TEST_PROJECT, TEST_PIPELINE),
),
patch.object(base.LlamaCloudIndex, "wait_for_completion"),
):
yield
def test_class() -> None:
names_of_base_classes = [b.__name__ for b in LlamaCloudIndex.__mro__]
assert BaseManagedIndex.__name__ in names_of_base_classes
def test_conflicting_index_identifiers():
def test_conflicting_index_identifiers() -> None:
with pytest.raises(ValueError):
LlamaCloudIndex(name="test", pipeline_id="test", index_id="test")
def test_from_documents_uses_provided_project_id(mock_client: MagicMock) -> None:
provided_project_id = "proj-123"
organization_id = "org-abc"
index_name = "my_new_index"
# Override resolve to return project with provided ID
test_project = Project(
id=provided_project_id, name="my_project", organization_id=organization_id
)
test_pipeline = Pipeline(
id="pipe-xyz",
name=index_name,
project_id=provided_project_id,
embedding_config=EMBEDDING_CONFIG,
)
with patch.object(
base, "resolve_project_and_pipeline", return_value=(test_project, test_pipeline)
):
docs = [Document(text="hello")]
index = LlamaCloudIndex.from_documents(
documents=docs,
name=index_name,
project_id=provided_project_id,
)
# Assert - project upsert not called; pipeline uses provided project_id
mock_client.projects.upsert_project.assert_not_called()
assert mock_client.pipelines.upsert_pipeline.call_count == 1
assert (
mock_client.pipelines.upsert_pipeline.call_args.kwargs["project_id"]
== provided_project_id
)
assert index.project.id == provided_project_id
def test_from_documents_upserts_project_when_project_id_missing(
mock_client: MagicMock,
) -> None:
organization_id = "org-xyz"
index_name = "my_new_index"
# Project is created when project_id is not provided
upserted_project = Project(
id="proj-999", name=DEFAULT_PROJECT_NAME, organization_id=organization_id
)
mock_client.projects.upsert_project.return_value = upserted_project
test_pipeline = Pipeline(
id="pipe-xyz",
name=index_name,
project_id=upserted_project.id,
embedding_config=EMBEDDING_CONFIG,
)
with patch.object(
base,
"resolve_project_and_pipeline",
return_value=(upserted_project, test_pipeline),
):
docs = [Document(text="world")]
index = LlamaCloudIndex.from_documents(
documents=docs,
name=index_name,
organization_id=organization_id,
)
# Assert - project was upserted with org id and default project name
mock_client.projects.upsert_project.assert_called_once()
kwargs = mock_client.projects.upsert_project.call_args.kwargs
assert kwargs["organization_id"] == organization_id
assert kwargs["request"].name == DEFAULT_PROJECT_NAME
# Pipeline created under the upserted project id
assert (
mock_client.pipelines.upsert_pipeline.call_args.kwargs["project_id"]
== upserted_project.id
)
assert index.project.id == upserted_project.id
Generated
+1 -1
View File
@@ -1596,7 +1596,7 @@ wheels = [
[[package]]
name = "llama-cloud-services"
version = "0.6.66"
version = "0.6.67"
source = { editable = "." }
dependencies = [
{ name = "click", version = "8.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" },