Compare commits

..

3 Commits

Author SHA1 Message Date
Clelia (Astra) Bertelli 3fd5127252 fix: skip examples for codespell 2025-07-31 18:12:22 +02:00
Clelia (Astra) Bertelli 43e74c36eb chore: correct broken link in readmes 2025-07-31 17:45:19 +02:00
Clelia (Astra) Bertelli e021446901 feat: restructure docs/examples 2025-07-31 17:35:46 +02:00
32 changed files with 2706 additions and 1615 deletions
+1 -4
View File
@@ -6,11 +6,8 @@ on:
push:
branches:
- main
paths:
- "py/**"
pull_request:
paths:
- "py/**"
env:
UV_VERSION: "0.7.20"
+1 -9
View File
@@ -1,13 +1,5 @@
name: Build Package - TypeScript
on:
push:
branches:
- main
paths:
- "ts/**"
pull_request:
paths:
- "ts/**"
on: [pull_request]
jobs:
pre_release:
+2 -4
View File
@@ -4,11 +4,9 @@ on:
push:
branches:
- main
paths:
- "ts/**"
pull_request:
paths:
- "ts/**"
branches:
- main
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
-38
View File
@@ -1,38 +0,0 @@
name: Test end-to-end - Python
on:
pull_request:
paths:
- "py/**"
env:
UV_VERSION: "0.7.20"
LLAMA_CLOUD_API_KEY: ${{ secrets.LLAMA_CLOUD_API_KEY }}
jobs:
test_e2e:
runs-on: ubuntu-latest
strategy:
# You can use PyPy versions in python-version.
# For example, pypy-2.7 and pypy-3.8
matrix:
python-version: ["3.12"]
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install uv
uses: astral-sh/setup-uv@v6
with:
version: ${{ env.UV_VERSION }}
- name: Set up Python
run: uv python install ${{ matrix.python-version }} && uv python pin ${{ matrix.python-version }}
- name: Run Tests
working-directory: py
run: uv run pytest unit_tests/ tests/ -v
- name: Remove virtual environment
working-directory: py
run: rm -rf .venv/
+2 -5
View File
@@ -4,14 +4,11 @@ on:
push:
branches:
- main
paths:
- "py/**"
pull_request:
paths:
- "py/**"
env:
UV_VERSION: "0.7.20"
LLAMA_CLOUD_API_KEY: ${{ secrets.LLAMA_CLOUD_API_KEY }}
jobs:
test:
@@ -35,7 +32,7 @@ jobs:
- name: Run Tests
working-directory: py
run: uv run pytest unit_tests/ -v
run: uv run -- pytest tests/**/test_*.py
- name: Remove virtual environment
working-directory: py
+4 -7
View File
@@ -4,11 +4,9 @@ on:
push:
branches:
- main
paths:
- "ts/**"
pull_request:
paths:
- "ts/**"
branches:
- main
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
@@ -17,8 +15,7 @@ env:
LLAMA_CLOUD_API_KEY: ${{ secrets.LLAMA_CLOUD_API_KEY }}
jobs:
test:
name: Test - TypeScript
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
@@ -34,4 +31,4 @@ jobs:
run: pnpm install --no-frozen-lockfile
- name: Run tests
working-directory: ts/llama_cloud_services/
run: pnpm test
run: pnpm test --run
+3 -3
View File
@@ -33,7 +33,7 @@ repos:
rev: v1.0.1
hooks:
- id: mypy
exclude: ^py/tests|^py/unit_tests
exclude: ^py/tests/
additional_dependencies:
[
"types-requests",
@@ -63,13 +63,13 @@ repos:
rev: v3.0.3
hooks:
- id: prettier
exclude: ^(uv.lock|ts/llama_cloud_services/pnpm-lock.yaml)
exclude: uv.lock
- repo: https://github.com/codespell-project/codespell
rev: v2.2.6
hooks:
- id: codespell
additional_dependencies: [tomli]
exclude: ^(uv.lock|docs|ts|examples)
exclude: ^(uv.lock|examples|ts)
args:
[
"--ignore-words-list",
@@ -147,7 +147,7 @@
"documents = []\n",
"\n",
"for i, page in enumerate(pages):\n",
" # loop through items of the page\n",
" # loop trough items of the page\n",
" for item in page[\"items\"]:\n",
" document = Document(\n",
" text=item[\"md\"], extra_info={\"bbox\": item[\"bBox\"], \"page\": i}\n",
+1 -1
View File
@@ -208,5 +208,5 @@ Another option (orthogonal to the above) is to break the document into smaller s
## Additional Resources
- [Example Notebook](docs/examples-py/extract/resume_screening.ipynb) - Detailed walkthrough of resume parsing
- [Example Notebook](examples/extract/resume_screening.ipynb) - Detailed walkthrough of resume parsing
- [Discord Community](https://discord.com/invite/eN6D2HQ4aX) - Get help and share feedback
+5 -5
View File
@@ -97,7 +97,7 @@ for page in result.pages:
print(page.structuredData)
```
See more details about the result object in the [example notebook](./docs/examples-py/parse/demo_json_tour.ipynb).
See more details about the result object in the [example notebook](./examples/parse/demo_json_tour.ipynb).
### Using with file object / bytes
@@ -153,10 +153,10 @@ Full documentation for `SimpleDirectoryReader` can be found on the [LlamaIndex D
Several end-to-end indexing examples can be found in the examples folder
- [Getting Started](docs/examples-py/parse/demo_basic.ipynb)
- [Advanced RAG Example](docs/examples-py/parse/demo_advanced.ipynb)
- [Raw API Usage](docs/examples-py/parse/demo_api.ipynb)
- [Result Object Tour](docs/examples-py/parse/demo_json_tour.ipynb)
- [Getting Started](./examples/parse/demo_basic.ipynb)
- [Advanced RAG Example](./examples/parse/demo_advanced.ipynb)
- [Raw API Usage](./examples/parse/demo_api.ipynb)
- [Result Object Tour](./examples/parse/demo_json_tour.ipynb)
## Documentation
@@ -181,15 +181,11 @@ class ExtractedFieldMetadata(BaseModel):
Metadata for an extracted data field, such as confidence, and citation information.
"""
reasoning: Optional[str] = Field(
None,
description="symbol for how the citation/confidence was derived: 'INFERRED FROM TEXT', 'VERBATIM EXTRACTION'",
)
confidence: Optional[float] = Field(
None,
description="The confidence score for the field, combined with parsing confidence if applicable",
)
extraction_confidence: Optional[float] = Field(
extracted_confidence: Optional[float] = Field(
None,
description="The confidence score for the field based on the extracted text only",
)
@@ -210,66 +206,42 @@ ExtractedFieldMetaDataDict = Dict[
def parse_extracted_field_metadata(
field_metadata: dict[str, Any],
) -> ExtractedFieldMetaDataDict:
return {
k: _parse_extracted_field_metadata_recursive(v)
for k, v in field_metadata.items()
if k not in _METADATA_FIELDS_SIBLING_TO_LEAF
}
_METADATA_FIELDS_SIBLING_TO_LEAF = {"reasoning"}
def _parse_extracted_field_metadata_recursive(
field_value: Any,
additional_fields: dict[str, Any] = {},
) -> Union[ExtractedFieldMetadata, Dict[str, Any], list[Any]]:
"""
Parse the extracted field metadata into a dictionary of field names to field metadata.
"""
result: ExtractedFieldMetaDataDict = {}
for field_name, field_value in field_metadata.items():
if isinstance(field_value, ExtractedFieldMetadata):
# support running this multiple times
result[field_name] = field_value
elif isinstance(field_value, dict):
if "confidence" in field_value or "citations" in field_value:
try:
validated = ExtractedFieldMetadata.model_validate(field_value)
if isinstance(field_value, ExtractedFieldMetadata):
# support running this multiple times
return field_value
elif isinstance(field_value, dict):
# reasoning explicitly excluded, as it is included next to subfields, for example
# "dimensions.width" is a leaf, but there will still potentially be a "dimensions.reasoning"
indicator_fields = {"confidence", "extraction_confidence", "citation"}
if len(indicator_fields.intersection(field_value.keys())) > 0:
try:
merged = {**field_value, **additional_fields}
validated = ExtractedFieldMetadata.model_validate(merged)
# grab the citation from the array. This is just an array for backwards compatibility.
if "citation" in field_value and len(field_value["citation"]) > 0:
first_citation = field_value["citation"][0]
if "page" in first_citation and isinstance(
first_citation["page"], numbers.Number
):
validated.page_number = int(first_citation["page"]) # type: ignore
if "matching_text" in first_citation and isinstance(
first_citation["matching_text"], str
):
validated.matching_text = first_citation["matching_text"]
return validated
except ValidationError:
pass
additional_fields = {
k: v
for k, v in field_value.items()
if k in _METADATA_FIELDS_SIBLING_TO_LEAF
}
return {
k: _parse_extracted_field_metadata_recursive(v, additional_fields)
for k, v in field_value.items()
if k not in _METADATA_FIELDS_SIBLING_TO_LEAF
}
elif isinstance(field_value, list):
return [_parse_extracted_field_metadata_recursive(item) for item in field_value]
else:
raise ValueError(
f"Invalid field value: {field_value}. Expected ExtractedFieldMetadata, dict, or list"
)
# grab the citation from the array. This is just an array for backwards compatibility.
if "citations" in field_value and len(field_value["citations"]) > 0:
first_citation = field_value["citations"][0]
if "page_number" in first_citation and isinstance(
first_citation["page_number"], numbers.Number
):
validated.page_number = int(first_citation["page_number"]) # type: ignore
if "matching_text" in first_citation and isinstance(
first_citation["matching_text"], str
):
validated.matching_text = first_citation["matching_text"]
result[field_name] = validated
continue
except ValidationError:
pass
result[field_name] = parse_extracted_field_metadata(field_value)
elif isinstance(field_value, list):
result[field_name] = [
parse_extracted_field_metadata(item) for item in field_value
]
else:
result[field_name] = field_value
return result
class ExtractedData(BaseModel, Generic[ExtractedT]):
+2 -2
View File
@@ -11,13 +11,13 @@ dev = [
[project]
name = "llama-parse"
version = "0.6.54"
version = "0.6.53"
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.54"]
dependencies = ["llama-cloud-services>=0.6.53"]
[project.scripts]
llama-parse = "llama_parse.cli.main:parse"
+1 -1
View File
@@ -17,7 +17,7 @@ dev = [
[project]
name = "llama-cloud-services"
version = "0.6.54"
version = "0.6.53"
description = "Tailored SDK clients for LlamaCloud services."
authors = [{name = "Logan Markewich", email = "logan@runllama.ai"}]
requires-python = ">=3.9,<4.0"
@@ -230,20 +230,20 @@ def test_parse_extracted_field_metadata():
raw_metadata = {
"name": {
"confidence": 0.95,
"citation": [{"page": 1, "matching_text": "John Smith"}],
"citations": [{"page_number": 1, "matching_text": "John Smith"}],
},
"age": {
"confidence": 0.87,
"citation": [
"citations": [
{
"page": 2.0, # Float page number
"page_number": 2.0, # Float page number
"matching_text": "25 years old",
}
],
},
"email": {
"confidence": 0.92,
"citation": [], # Empty citations
"citations": [], # Empty citations
},
}
@@ -268,110 +268,6 @@ def test_parse_extracted_field_metadata():
assert result["email"].confidence == 0.92
def test_parse_extracted_field_metadata_complex():
"""Test parse_extracted_field_metadata with new citation format and reasoning field."""
raw_metadata = {
"title": {
"reasoning": "Combined key parametrics and construction from the datasheet for a structured title.",
"citation": [
{
"page": 1,
"matching_text": "PHE844/F844, Film, Metallized Polypropylene, Safety, 0.47 uF",
}
],
"extraction_confidence": 0.9470628580889779,
"confidence": 0.9470628580889779,
},
"manufacturer": {
"reasoning": "VERBATIM EXTRACTION",
"citation": [{"page": 1, "matching_text": "YAGEO KEMET"}],
"extraction_confidence": 0.9997446550976602,
"confidence": 0.9997446550976602,
},
"features": [
{
"reasoning": "VERBATIM EXTRACTION",
"citation": [
{"page": 1, "matching_text": "Features</td><td>EMI Safety"}
],
"extraction_confidence": 0.9999308195540074,
"confidence": 0.9999308195540074,
},
{
"reasoning": "VERBATIM EXTRACTION",
"citation": [
{"page": 1, "matching_text": "THB Performance</td><td>Yes"}
],
"extraction_confidence": 0.8642493886452225,
"confidence": 0.8642493886452225,
},
],
"dimensions": {
"length": {
"citation": [{"page": 1, "matching_text": "L</td><td>41mm MAX"}],
"extraction_confidence": 0.8986941382802304,
"confidence": 0.8986941382802304,
},
"width": {
"citation": [{"page": 1, "matching_text": "T</td><td>13mm MAX"}],
"extraction_confidence": 0.9999377974447091,
"confidence": 0.9999377974447091,
},
"reasoning": "VERBATIM EXTRACTION",
},
}
result = parse_extracted_field_metadata(raw_metadata)
assert result == {
"title": ExtractedFieldMetadata(
reasoning="Combined key parametrics and construction from the datasheet for a structured title.",
confidence=0.9470628580889779,
extraction_confidence=0.9470628580889779,
page_number=1,
matching_text="PHE844/F844, Film, Metallized Polypropylene, Safety, 0.47 uF",
),
"manufacturer": ExtractedFieldMetadata(
reasoning="VERBATIM EXTRACTION",
confidence=0.9997446550976602,
extraction_confidence=0.9997446550976602,
page_number=1,
matching_text="YAGEO KEMET",
),
"features": [
ExtractedFieldMetadata(
reasoning="VERBATIM EXTRACTION",
confidence=0.9999308195540074,
extraction_confidence=0.9999308195540074,
page_number=1,
matching_text="Features</td><td>EMI Safety",
),
ExtractedFieldMetadata(
reasoning="VERBATIM EXTRACTION",
confidence=0.8642493886452225,
extraction_confidence=0.8642493886452225,
page_number=1,
matching_text="THB Performance</td><td>Yes",
),
],
"dimensions": {
"length": ExtractedFieldMetadata(
reasoning="VERBATIM EXTRACTION",
confidence=0.8986941382802304,
extraction_confidence=0.8986941382802304,
page_number=1,
matching_text="L</td><td>41mm MAX",
),
"width": ExtractedFieldMetadata(
reasoning="VERBATIM EXTRACTION",
confidence=0.9999377974447091,
extraction_confidence=0.9999377974447091,
page_number=1,
matching_text="T</td><td>13mm MAX",
),
},
}
def create_file(
id: str = "file-456",
name: str = "resume.pdf",
@@ -394,12 +290,12 @@ def create_extract_run(
extraction_metadata: Dict[str, Any] = {
"name": {
"confidence": 0.95,
"citation": [{"page": 1, "matching_text": "John Doe"}],
"citations": [{"page_number": 1, "matching_text": "John Doe"}],
},
"age": {"confidence": 0.87},
"email": {
"confidence": 0.92,
"citation": [{"page": 1, "matching_text": "john@example.com"}],
"citations": [{"page_number": 1, "matching_text": "john@example.com"}],
},
},
data_schema: Dict[str, Any] = {},
+2 -2
View File
@@ -124,8 +124,8 @@ def extraction_agent(test_case: TestCase, extractor: LlamaExtract):
@pytest.mark.skipif(
"CI" in os.environ or not LLAMA_CLOUD_API_KEY,
reason="LLAMA_CLOUD_API_KEY not set or CI environment not suitable for benchmarking",
"CI" in os.environ,
reason="CI environment is not suitable for benchmarking",
)
@pytest.mark.parametrize("test_case", get_test_cases(), ids=lambda x: x.name)
@pytest.mark.asyncio(loop_scope="session")
+11 -5
View File
@@ -16,6 +16,7 @@ from llama_cloud import (
from llama_cloud.client import LlamaCloud
from llama_index.core.bridge.pydantic import BaseModel
from llama_index.core.constants import DEFAULT_BASE_URL
from llama_index.core.indices.managed.base import BaseManagedIndex
from llama_index.core.schema import Document, ImageNode
from llama_cloud_services.index import (
LlamaCloudIndex,
@@ -27,8 +28,6 @@ api_key = os.environ.get("LLAMA_CLOUD_API_KEY", None)
organization_id = os.environ.get("LLAMA_CLOUD_ORGANIZATION_ID", None)
project_name = os.environ.get("LLAMA_CLOUD_PROJECT_NAME", "framework_integration_test")
print("api-key", api_key, "base-url", base_url)
@pytest.fixture()
def remote_file() -> Tuple[str, str]:
@@ -92,6 +91,16 @@ def _setup_index_with_file(
return pipeline
def test_class():
names_of_base_classes = [b.__name__ for b in LlamaCloudIndex.__mro__]
assert BaseManagedIndex.__name__ in names_of_base_classes
def test_conflicting_index_identifiers():
with pytest.raises(ValueError):
LlamaCloudIndex(name="test", pipeline_id="test", index_id="test")
@pytest.mark.skipif(
not base_url or not api_key, reason="No platform base url or api key set"
)
@@ -353,9 +362,6 @@ async def test_page_figure_retrieval(index_name: str, local_figures_file: str):
not base_url or not api_key, reason="No platform base url or api key set"
)
@pytest.mark.asyncio
@pytest.mark.skip(
reason="Consistently failing with 'Server disconnected without sending a response'"
)
async def test_composite_retriever(index_name: str):
"""Test the LlamaCloudCompositeRetriever with multiple indices."""
# Create first index with documents
View File
-16
View File
@@ -1,16 +0,0 @@
import pytest
from llama_index.core.indices.managed.base import BaseManagedIndex
from llama_cloud_services.index import (
LlamaCloudIndex,
)
def test_class():
names_of_base_classes = [b.__name__ for b in LlamaCloudIndex.__mro__]
assert BaseManagedIndex.__name__ in names_of_base_classes
def test_conflicting_index_identifiers():
with pytest.raises(ValueError):
LlamaCloudIndex(name="test", pipeline_id="test", index_id="test")
Generated
+2 -2
View File
@@ -734,7 +734,7 @@ name = "exceptiongroup"
version = "1.3.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "typing-extensions", marker = "python_full_version < '3.11'" },
{ name = "typing-extensions", marker = "python_full_version < '3.13'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/0b/9f/a65090624ecf468cdca03533906e7c69ed7588582240cfe7cc9e770b50eb/exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88", size = 29749, upload-time = "2025-05-10T17:42:51.123Z" }
wheels = [
@@ -1587,7 +1587,7 @@ wheels = [
[[package]]
name = "llama-cloud-services"
version = "0.6.54"
version = "0.6.53"
source = { editable = "." }
dependencies = [
{ name = "click", version = "8.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" },
+23 -56
View File
@@ -13,26 +13,17 @@ from pathlib import Path
def get_current_versions() -> tuple[str, str, str]:
"""Get current versions from both pyproject.toml files."""
# Read main pyproject.toml
main_content = Path("py/pyproject.toml").read_text()
main_content = Path("pyproject.toml").read_text()
main_doc = tomlkit.parse(main_content)
main_version = main_doc["project"]["version"]
main_version = main_doc["tool"]["poetry"]["version"]
# Read llama_parse/pyproject.toml
llama_parse_content = Path("py/llama_parse/pyproject.toml").read_text()
llama_parse_content = Path("llama_parse/pyproject.toml").read_text()
llama_parse_doc = tomlkit.parse(llama_parse_content)
llama_parse_version = llama_parse_doc["project"]["version"]
# Find llama-cloud-services dependency in the dependencies list
dependency_version = None
for dep in llama_parse_doc["project"]["dependencies"]:
if isinstance(dep, str) and dep.startswith("llama-cloud-services"):
dependency_version = (
dep.split("==")[1]
if "==" in dep
else dep.split(">=")[1]
if ">=" in dep
else None
)
break
llama_parse_version = llama_parse_doc["tool"]["poetry"]["version"]
dependency_version = llama_parse_doc["tool"]["poetry"]["dependencies"][
"llama-cloud-services"
]
return str(main_version), str(llama_parse_version), str(dependency_version)
@@ -62,22 +53,19 @@ def validate_versions(
def set_version(version: str) -> None:
"""Set version across all pyproject.toml files using tomlkit to preserve formatting."""
# Update main pyproject.toml
main_content = Path("py/pyproject.toml").read_text()
main_content = Path("pyproject.toml").read_text()
main_doc = tomlkit.parse(main_content)
main_doc["project"]["version"] = version
Path("py/pyproject.toml").write_text(tomlkit.dumps(main_doc))
main_doc["tool"]["poetry"]["version"] = version
Path("pyproject.toml").write_text(tomlkit.dumps(main_doc))
# Update llama_parse/pyproject.toml
llama_parse_content = Path("py/llama_parse/pyproject.toml").read_text()
llama_parse_content = Path("llama_parse/pyproject.toml").read_text()
llama_parse_doc = tomlkit.parse(llama_parse_content)
llama_parse_doc["project"]["version"] = version
for dep_index, dep in enumerate(llama_parse_doc["project"]["dependencies"]):
if isinstance(dep, str) and dep.startswith("llama-cloud-services"):
llama_parse_doc["project"]["dependencies"][
dep_index
] = f"llama-cloud-services>={version}"
break
Path("py/llama_parse/pyproject.toml").write_text(tomlkit.dumps(llama_parse_doc))
llama_parse_doc["tool"]["poetry"]["version"] = version
llama_parse_doc["tool"]["poetry"]["dependencies"][
"llama-cloud-services"
] = f">={version}"
Path("llama_parse/pyproject.toml").write_text(tomlkit.dumps(llama_parse_doc))
click.echo(f"Updated all versions to {version}")
@@ -90,7 +78,7 @@ def get_current_branch() -> str:
return result.stdout.strip()
def create_if_not_exists(version: str) -> None:
def create_and_push_tag(version: str) -> None:
"""Create a git tag and push it."""
current_branch = get_current_branch()
if current_branch != "main":
@@ -100,26 +88,12 @@ def create_if_not_exists(version: str) -> None:
sys.exit(1)
tag_name = f"v{version}"
if not tag_exists(version):
# Create tag
subprocess.run(["git", "tag", tag_name], check=True)
click.echo(f"Created tag {tag_name}")
else:
click.echo(f"Tag {tag_name} already exists")
# Create tag
subprocess.run(["git", "tag", tag_name], check=True)
click.echo(f"Created tag {tag_name}")
def tag_exists(version: str) -> bool:
"""Check if a git tag exists."""
tag_name = f"v{version}"
result = subprocess.run(
["git", "tag", "-l", tag_name], capture_output=True, text=True, check=True
)
return tag_name in result.stdout.strip()
def push_tag(version: str) -> None:
"""Push a git tag."""
tag_name = f"v{version}"
# Push tag
subprocess.run(["git", "push", "origin", tag_name], check=True)
click.echo(f"Pushed tag {tag_name}")
@@ -160,20 +134,13 @@ def set(version: str) -> None:
@click.option(
"--version", help="Version to tag (uses current version if not specified)"
)
@click.option(
"--push",
is_flag=True,
help="Push the tag to the remote repository",
)
def tag(version: str | None = None, push: bool = False) -> None:
def tag(version: str | None = None) -> None:
"""Create and push a git tag for the current version."""
if not version:
main_version, _, _ = get_current_versions()
version = main_version
create_if_not_exists(version)
if push:
push_tag(version)
create_and_push_tag(version)
if __name__ == "__main__":
+8 -8
View File
@@ -1,6 +1,6 @@
{
"name": "llama-cloud-services",
"version": "0.2.0",
"version": "0.1.0",
"type": "module",
"license": "MIT",
"scripts": {
@@ -9,7 +9,7 @@
"dev": "bunchee --watch",
"lint": "eslint src/ --ignore-pattern client/*.ts --no-warn-ignored",
"format": "prettier --write ./src/",
"test": "vitest run --testTimeout=60000",
"test": "vitest",
"test:watch": "vitest --watch",
"test:ui": "vitest --ui",
"test:coverage": "vitest --coverage"
@@ -89,12 +89,12 @@
"@eslint/js": "^9.32.0",
"@hey-api/client-fetch": "^0.10.1",
"@hey-api/openapi-ts": "^0.67.5",
"@llamaindex/core": "^0.6.19",
"@llama-flow/core": "^0.4.1",
"@llamaindex/core": "^0.6.18",
"@llamaindex/env": "^0.1.30",
"@llamaindex/workflow-core": "^0.4.1",
"@types/node": "^20.19.9",
"@typescript-eslint/eslint-plugin": "^8.38.0",
"@typescript-eslint/parser": "^8.38.0",
"@types/node": "^20.0.0",
"@vitest/coverage-v8": "^2.0.0",
"@vitest/ui": "^2.0.0",
"bunchee": "^6.5.4",
@@ -107,12 +107,12 @@
"vitest": "^2.0.0"
},
"peerDependencies": {
"@llamaindex/core": "^0.6.19",
"@llama-flow/core": "^0.4.1",
"@llamaindex/core": "^0.6.18",
"@llamaindex/env": "^0.1.30",
"@llamaindex/workflow-core": "^0.4.1"
"llamaindex": "^0.11.23"
},
"dependencies": {
"ajv": "^8.17.1",
"p-retry": "^6.2.1",
"zod": "^3.25.76"
},
+2564 -1158
View File
File diff suppressed because it is too large Load Diff
+21 -18
View File
@@ -1,10 +1,8 @@
import type { BaseNodePostprocessor } from "@llamaindex/core/postprocessor";
import {
RetrieverQueryEngine,
type BaseQueryEngine,
} from "@llamaindex/core/query-engine";
import type { BaseQueryEngine } from "@llamaindex/core/query-engine";
import type { BaseSynthesizer } from "@llamaindex/core/response-synthesizers";
import type { Document } from "@llamaindex/core/schema";
import { RetrieverQueryEngine } from "llamaindex/engines";
import type { CloudRetrieveParams } from "./LlamaCloudRetriever.js";
import { LlamaCloudRetriever } from "./LlamaCloudRetriever.js";
import type { CloudConstructorParams } from "./type.js";
@@ -27,14 +25,9 @@ import {
} from "./api";
import type { BaseRetriever } from "@llamaindex/core/retriever";
import { getEnv } from "@llamaindex/env";
import { createQueryEngineTool, type QueryToolParams } from "./query-tool.js";
import type { BaseTool } from "@llamaindex/core/llms";
type QueryEngineParams = {
responseSynthesizer?: BaseSynthesizer;
preFilters?: unknown;
nodePostprocessors?: BaseNodePostprocessor[];
} & CloudRetrieveParams;
import type { QueryToolParams } from "llamaindex/indices";
import { Settings } from "llamaindex";
import { QueryEngineTool } from "llamaindex/tools";
export class LlamaCloudIndex {
params: CloudConstructorParams;
@@ -45,7 +38,7 @@ export class LlamaCloudIndex {
}
private async waitForPipelineIngestion(
verbose = false,
verbose = Settings.debug,
raiseOnError = false,
): Promise<void> {
const pipelineId = await this.getPipelineId();
@@ -90,7 +83,7 @@ export class LlamaCloudIndex {
private async waitForDocumentIngestion(
docIds: string[],
verbose = false,
verbose = Settings.debug,
raiseOnError = false,
): Promise<void> {
const pipelineId = await this.getPipelineId();
@@ -263,7 +256,13 @@ export class LlamaCloudIndex {
return new LlamaCloudRetriever({ ...this.params, ...params });
}
asQueryEngine(params?: QueryEngineParams): BaseQueryEngine {
asQueryEngine(
params?: {
responseSynthesizer?: BaseSynthesizer;
preFilters?: unknown;
nodePostprocessors?: BaseNodePostprocessor[];
} & CloudRetrieveParams,
): BaseQueryEngine {
const retriever = new LlamaCloudRetriever({
...this.params,
...params,
@@ -275,15 +274,19 @@ export class LlamaCloudIndex {
);
}
asQueryTool(params: QueryEngineParams & QueryToolParams): BaseTool {
return createQueryEngineTool({
asQueryTool(params: QueryToolParams): QueryEngineTool {
if (params.options) {
params.retriever = this.asRetriever(params.options);
}
return new QueryEngineTool({
queryEngine: this.asQueryEngine(params),
metadata: params?.metadata,
includeSourceNodes: params?.includeSourceNodes ?? false,
});
}
queryTool(params: QueryEngineParams & QueryToolParams) {
queryTool(params: QueryToolParams): QueryEngineTool {
return this.asQueryTool(params);
}
@@ -261,7 +261,8 @@ export class AgentClient<T = unknown> {
}
}
export interface AgentDataClientOptions {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export interface AgentDataClientOptions<T = unknown> {
/** API key for the client */
apiKey?: string;
/** Base URL for the client */
@@ -28,31 +28,6 @@ export type ComparisonOperator =
*/
export type FilterOperation = RawFilterOperation;
/**
* Metadata for an extracted field, including confidence and citation information
*/
export interface ExtractedFieldMetadata {
/** The reasoning for the confidence score */
reasoning?: string;
/** The confidence score for the field, combined with parsing confidence if applicable */
confidence?: number;
/** The confidence score for the field based on the extracted text only */
extraction_confidence?: number;
/** The page number that the field occurred on */
page_number?: number;
/** The original text this field's value was derived from */
matching_text?: string;
}
/**
* Dictionary mapping field names to their metadata
* Values can be ExtractedFieldMetadata objects, nested dictionaries, or arrays
*/
export type ExtractedFieldMetadataDict = Record<
string,
ExtractedFieldMetadata | Record<string, unknown> | unknown[]
>;
/**
* Base extracted data interface
*/
@@ -60,13 +35,11 @@ export interface ExtractedData<T = unknown> {
/** The original data that was extracted from the document. For tracking changes. Should not be updated. */
original_data: T;
/** The latest state of the data. Will differ if data has been updated. */
data: T;
data?: T;
/** The status of the extracted data. Prefer to use the StatusType values, but any string is allowed. */
status: StatusType | string;
/** The overall confidence score for the extracted data. */
overall_confidence?: number;
/** Page links, and perhaps eventually bounding boxes, for individual fields in the extracted data. */
field_metadata?: ExtractedFieldMetadataDict;
/** Confidence scores, if any, for each primitive field in the original_data data. */
confidence?: Record<string, unknown>;
/** The ID of the file that was used to extract the data. */
file_id?: string;
/** The name of the file that was used to extract the data. */
+2 -2
View File
@@ -1,5 +1,5 @@
import { workflowEvent } from "@llamaindex/workflow-core";
import { zodEvent } from "@llamaindex/workflow-core/util/zod";
import { workflowEvent } from "@llama-flow/core";
import { zodEvent } from "@llama-flow/core/util/zod";
import { z } from "zod";
import { parseFormSchema } from "./schema";
+4 -7
View File
@@ -1,11 +1,8 @@
import { createClient, createConfig } from "@hey-api/client-fetch";
import {
createWorkflow,
type InferWorkflowEventData,
} from "@llamaindex/workflow-core";
import { createStatefulMiddleware } from "@llamaindex/workflow-core/middleware/state";
import { withTraceEvents } from "@llamaindex/workflow-core/middleware/trace-events";
import { pRetryHandler } from "@llamaindex/workflow-core/util/p-retry";
import { createWorkflow, type InferWorkflowEventData } from "@llama-flow/core";
import { createStatefulMiddleware } from "@llama-flow/core/middleware/state";
import { withTraceEvents } from "@llama-flow/core/middleware/trace-events";
import { pRetryHandler } from "@llama-flow/core/util/p-retry";
import { fs, getEnv, path } from "@llamaindex/env";
import {
type BodyUploadFileApiV1ParsingUploadPost,
-39
View File
@@ -1,39 +0,0 @@
import type { JSONValue } from "@llamaindex/core/global";
import type { ToolMetadata } from "@llamaindex/core/llms";
import type { BaseQueryEngine } from "@llamaindex/core/query-engine";
import { tool } from "@llamaindex/core/tools";
import { z } from "zod";
const DEFAULT_NAME = "llama_cloud_index_tool";
const DEFAULT_DESCRIPTION =
"Useful for retrieving relevant information from document stored in a LlamaCloud Index";
export type QueryToolParams = {
metadata?: Omit<ToolMetadata, "parameters"> | undefined;
includeSourceNodes?: boolean;
};
export function createQueryEngineTool(
options: { queryEngine: BaseQueryEngine } & QueryToolParams,
) {
const { queryEngine, metadata, includeSourceNodes } = options;
return tool({
name: metadata?.name ?? DEFAULT_NAME,
description: metadata?.description ?? DEFAULT_DESCRIPTION,
parameters: z.object({
query: z.string({
description: "The query to search for",
}),
}),
execute: async ({ query }) => {
const response = await queryEngine.query({ query });
if (!includeSourceNodes) {
return { content: response.message.content } as unknown as JSONValue;
}
return {
content: response.message.content,
sourceNodes: response.sourceNodes,
} as unknown as JSONValue;
},
});
}
@@ -350,25 +350,6 @@ describe("Integration Tests", () => {
}
});
it.skipIf(skipIfNoApiKey)("should create query engine tool", async () => {
try {
const queryEngineTool = index.asQueryTool({
metadata: {
name: "test-tool",
description: "Test tool description",
},
});
expect(queryEngineTool).toBeDefined();
expect(typeof queryEngineTool.call).toBe("function");
expect(queryEngineTool.metadata.name).toBe("test-tool");
expect(queryEngineTool.metadata.description).toBe(
"Test tool description",
);
} catch (error) {
console.warn("Query engine tool creation test failed:", error.message);
}
});
it.skipIf(skipIfNoApiKey)(
"should get pipeline and project IDs",
async () => {
+2 -1
View File
@@ -14,9 +14,10 @@
"rootDir": "./src",
"outDir": "./dist/type",
"tsBuildInfoFile": "./dist/.tsbuildinfo",
"emitDeclarationOnly": true,
"incremental": true,
"lib": ["ES2022", "DOM", "DOM.Iterable", "DOM.AsyncIterable"],
"types": ["node"]
"types": []
},
"include": ["./src"],
"exclude": ["node_modules"]