Compare commits

...

40 Commits

Author SHA1 Message Date
Logan Markewich a3954f3dda async batch 2024-02-19 17:38:09 -06:00
Logan Markewich b779e231bf version bump 2024-02-19 13:27:26 -06:00
Haotian Zhang de12de1437 Merge pull request #18 from run-llama/hz/demo_v5
upd demo results
2024-02-18 23:35:37 -05:00
Haotian Zhang 5274ea5277 cr 2024-02-18 23:32:38 -05:00
Haotian Zhang 398d775122 cr 2024-02-18 23:29:38 -05:00
Haotian Zhang aca18e12ef Merge pull request #17 from run-llama/hz/demo_v4
clean up notebook baseline method
2024-02-18 22:55:18 -05:00
Haotian Zhang 270c2ed0aa clean up notebook baseline 2024-02-18 22:49:49 -05:00
Logan 2cf960196f Merge pull request #15 from run-llama/logan/update_docs
Logan/update docs
2024-02-18 19:22:57 -06:00
Logan 6b83edc8fd Merge branch 'main' into logan/update_docs 2024-02-18 19:22:50 -06:00
Logan Markewich 711822223a [version] v0.3.0 2024-02-18 18:18:49 -06:00
Logan 8e6872b57c Merge pull request #16 from run-llama/jerry/fix_v10
nit: fix README instructions for v0.10 compatibility
2024-02-18 18:17:42 -06:00
Logan Markewich c3a30898af prioritize os env 2024-02-18 16:01:59 -06:00
Logan Markewich f3f6fb0444 enusre URL 2024-02-18 15:51:42 -06:00
Logan Markewich 641b6d61a7 simon comment 2024-02-18 15:50:44 -06:00
Logan Markewich c0996a64a7 allow api key 2024-02-17 23:05:22 -06:00
Logan Markewich a8904f39e2 poetry lock 2024-02-17 22:58:20 -06:00
Logan Markewich 81011f6336 update advanced demo notebook 2024-02-17 21:58:08 -06:00
Haotian Zhang 117b193ee9 Merge pull request #13 from run-llama/hz/demo_V3
Refactor demo structure
2024-02-15 22:23:35 -05:00
Haotian Zhang bd724a7939 cr 2024-02-15 22:19:48 -05:00
Haotian Zhang 866cdca216 Merge pull request #12 from run-llama/hz/demo_v1
New Llama Parser Demo
2024-02-15 15:48:59 -05:00
Haotian Zhang ba321ac5b0 cr 2024-02-15 15:38:30 -05:00
Haotian Zhang 8fab0ac2ad New Llama Parse Demo 2024-02-15 15:36:45 -05:00
Haotian Zhang 563eb936e4 New Llama parser Demo 2024-02-15 15:34:30 -05:00
Simon Suo 09c069de4b Merge pull request #10 from run-llama/suo/bump_version
Bump version
2024-02-13 16:07:38 -08:00
Simon Suo 1224c3b40e wip 2024-02-13 16:07:16 -08:00
Simon Suo 1001a1586f Merge pull request #9 from run-llama/suo/handle_exception
Handle error from API
2024-02-13 16:06:05 -08:00
Simon Suo cb01f6e002 wip 2024-02-13 12:57:00 -08:00
Simon Suo 6ffc59d96a Merge pull request #8 from alexleventer/main
Fix readme typos
2024-02-12 12:04:39 -08:00
Logan Markewich 860b8e58f8 v0.2.0 to work with llama-index v0.10.0 2024-02-12 13:52:49 -06:00
Alex Leventer 615699e2aa Fix readme typos 2024-02-09 13:44:31 -08:00
Logan Markewich 7c8436373e update timeout + print 2024-02-02 20:13:30 -08:00
Logan Markewich cfe97c6777 update readme 2024-02-02 19:38:05 -08:00
Logan Markewich fdbc626789 add verbose option + progress 2024-02-02 19:37:27 -08:00
Logan Markewich 1638349028 rename 2024-02-02 16:13:27 -08:00
Simon Suo 17058d4ddb Add hackathon TOS 2024-02-02 16:09:42 -08:00
Haotian Zhang 2661f330e2 Merge pull request #6 from run-llama/hz/demo_v2
change demo
2024-02-02 15:24:01 -08:00
Haotian Zhang 46b9b653c1 change 2024-02-02 15:22:23 -08:00
Logan Markewich c7ca760e4a update advanced notebook 2024-02-02 13:42:29 -08:00
Haotian Zhang deb9cb23cc cr 2024-02-02 13:10:12 -08:00
Haotian Zhang 063ed8ee46 cr 2024-02-02 13:07:31 -08:00
6 changed files with 832 additions and 581 deletions
+17 -4
View File
@@ -1,6 +1,6 @@
# LlamaParse (Preview)
LlamaParse is an API created by LlamaIndex to effeciently parse and represent files for effecient retrieval and context augmentation using LlamaIndex frameworks.
LlamaParse is an API created by LlamaIndex to efficiently parse and represent files for efficient retrieval and context augmentation using LlamaIndex frameworks.
LlamaParse directly integrates with [LlamaIndex](https://github.com/run-llama/llama_index).
@@ -26,14 +26,22 @@ from llama_parse import LlamaParse
parser = LlamaParse(
api_key="llx-...", # can also be set in your env as LLAMA_CLOUD_API_KEY
result_type="markdown" # "markdown" and "text" are available
result_type="markdown", # "markdown" and "text" are available
num_workers=4, # if multiple files passed, split in `num_workers` API calls
verbose=True
)
# sync
documents = parser.load_data("./my_file.pdf")
# sync batch
documents = parser.load_data(["./my_file1.pdf", "./my_file2.pdf"])
# async
documents = await parser.aload_data("./my_file.pdf")
# async batch
documents = await parser.aload_data(["./my_file1.pdf", "./my_file2.pdf"])
```
## Using with `SimpleDirectoryReader`
@@ -49,7 +57,8 @@ from llama_index.core import SimpleDirectoryReader
parser = LlamaParse(
api_key="llx-...", # can also be set in your env as LLAMA_CLOUD_API_KEY
result_type="markdown" # "markdown" and "text" are available
result_type="markdown", # "markdown" and "text" are available
verbose=True
)
file_extractor = {".pdf": parser}
@@ -60,8 +69,12 @@ Full documentation for `SimpleDirectoryReader` can be found on the [LlamaIndex D
## Examples
Serveral end-to-end indexing examples can be found in the examples folder
Several end-to-end indexing examples can be found in the examples folder
- [Getting Started](examples/demo_basic.ipynb)
- [Advanced RAG Example](examples/demo_advanced.ipynb)
- [Raw API Usage](examples/demo_api.ipynb)
## Terms of Service
See the [Terms of Service Here](./TOS.pdf).
BIN
View File
Binary file not shown.
File diff suppressed because one or more lines are too long
+106 -45
View File
@@ -1,14 +1,19 @@
import os
import asyncio
import httpx
import mimetypes
import time
from enum import Enum
from typing import List, Optional
from typing import List, Optional, Union
from llama_index.bridge.pydantic import Field, validator
from llama_index.readers.base import BasePydanticReader
from llama_index.schema import Document
from llama_index.core.async_utils import run_jobs
from llama_index.core.bridge.pydantic import Field, validator
from llama_index.core.constants import DEFAULT_BASE_URL
from llama_index.core.readers.base import BasePydanticReader
from llama_index.core.schema import Document
nest_asyncio_err = "cannot be called from a running event loop"
nest_asyncio_msg = "The event loop is already running. Add `import nest_asyncio; nest_asyncio.apply()` to your code to fix this issue."
class ResultType(str, Enum):
"""The result type for the parser."""
@@ -22,12 +27,18 @@ class LlamaParse(BasePydanticReader):
api_key: str = Field(default="", description="The API key for the LlamaParse API.")
base_url: str = Field(
default="https://api.cloud.llamaindex.ai/api/parsing",
default=DEFAULT_BASE_URL,
description="The base URL of the Llama Parsing API.",
)
result_type: ResultType = Field(
default=ResultType.TXT, description="The result type for the parser."
)
num_workers: int = Field(
default=4,
gt=0,
lt=10,
description="The number of workers to use sending API requests for parsing."
)
check_interval: int = Field(
default=1,
description="The interval in seconds to check if the parsing is done.",
@@ -36,6 +47,9 @@ class LlamaParse(BasePydanticReader):
default=2000,
description="The maximum timeout in seconds to wait for the parsing to finish.",
)
verbose: bool = Field(
default=True, description="Whether to print the progress of the parsing."
)
@validator("api_key", pre=True, always=True)
def validate_api_key(cls, v: str) -> str:
@@ -48,55 +62,102 @@ class LlamaParse(BasePydanticReader):
return api_key
return v
@validator("base_url", pre=True, always=True)
def validate_base_url(cls, v: str) -> str:
"""Validate the base URL."""
url = os.getenv("LLAMA_CLOUD_BASE_URL", None)
return url or v or DEFAULT_BASE_URL
def load_data(self, file_path: str, extra_info: Optional[dict] = None) -> List[Document]:
async def _aload_data(self, file_path: str, extra_info: Optional[dict] = None) -> List[Document]:
"""Load data from the input path."""
return asyncio.run(self.aload_data(file_path, extra_info))
try:
file_path = str(file_path)
if not file_path.endswith(".pdf"):
raise Exception("Currently, only PDF files are supported.")
async def aload_data(self, file_path: str, extra_info: Optional[dict] = None) -> List[Document]:
"""Load data from the input path."""
file_path = str(file_path)
if not file_path.endswith(".pdf"):
raise Exception("Currently, only PDF files are supported.")
extra_info = extra_info or {}
extra_info["file_path"] = file_path
extra_info = extra_info or {}
extra_info["file_path"] = file_path
headers = {"Authorization": f"Bearer {self.api_key}"}
headers = {"Authorization": f"Bearer {self.api_key}"}
# load data, set the mime type
with open(file_path, "rb") as f:
mime_type = mimetypes.guess_type(file_path)[0]
files = {"file": (f.name, f, mime_type)}
# load data, set the mime type
with open(file_path, "rb") as f:
mime_type = mimetypes.guess_type(file_path)[0]
files = {"file": (f.name, f, mime_type)}
# send the request, start job
url = f"{self.base_url}/api/parsing/upload"
async with httpx.AsyncClient(timeout=self.max_timeout) as client:
response = await client.post(url, files=files, headers=headers)
if not response.is_success:
raise Exception(f"Failed to parse the PDF file: {response.text}")
# send the request, start job
url = f"{self.base_url}/upload"
async with httpx.AsyncClient() as client:
response = await client.post(url, files=files, headers=headers)
if not response.is_success:
raise Exception(f"Failed to parse the PDF file: {response.text}")
# check the status of the job, return when done
job_id = response.json()["id"]
if self.verbose:
print("Started parsing the file under job_id %s" % job_id)
result_url = f"{self.base_url}/api/parsing/job/{job_id}/result/{self.result_type.value}"
# check the status of the job, return when done
job_id = response.json()["id"]
print("Started parsing the file under job_id %s" % job_id)
result_url = f"{self.base_url}/job/{job_id}/result/{self.result_type.value}"
start = time.time()
tries = 0
while True:
await asyncio.sleep(self.check_interval)
async with httpx.AsyncClient(timeout=self.max_timeout) as client:
tries += 1
result = await client.get(result_url, headers=headers)
start = time.time()
while True:
await asyncio.sleep(self.check_interval)
async with httpx.AsyncClient() as client:
result = await client.get(result_url, headers=headers)
if result.status_code == 404:
end = time.time()
if end - start > self.max_timeout:
raise Exception(
f"Timeout while parsing the PDF file: {response.text}"
)
if self.verbose and tries % 10 == 0:
print(".", end="", flush=True)
continue
if not result.is_success:
if time.time() - start > self.max_timeout:
raise Exception(
f"Timeout while parsing the PDF file: {response.text}"
if result.status_code == 400:
detail = result.json().get("detail", "Unknown error")
raise Exception(f"Failed to parse the PDF file: {detail}")
return [
Document(
text=result.json()[self.result_type.value],
metadata=extra_info,
)
continue
]
except Exception as e:
print("Error while parsing the PDF file: ", e)
return []
async def aload_data(self, file_path: Union[List[str], str], extra_info: Optional[dict] = None) -> List[Document]:
"""Load data from the input path."""
if isinstance(file_path, str):
return await self._aload_data(file_path, extra_info=extra_info)
elif isinstance(file_path, list):
jobs = [self._aload_data(f, extra_info=extra_info) for f in file_path]
try:
results = await run_jobs(jobs, workers=self.num_workers)
# return flattened results
return [item for sublist in results for item in sublist]
except RuntimeError as e:
if nest_asyncio_err in str(e):
raise RuntimeError(nest_asyncio_msg)
else:
raise e
else:
raise ValueError("The input file_path must be a string or a list of strings.")
return [
Document(
text=result.json()[self.result_type.value],
metadata=extra_info,
)
]
def load_data(self, file_path: Union[List[str], str], extra_info: Optional[dict] = None) -> List[Document]:
"""Load data from the input path."""
try:
return asyncio.run(self.aload_data(file_path, extra_info))
except RuntimeError as e:
if nest_asyncio_err in str(e):
raise RuntimeError(nest_asyncio_msg)
else:
raise e
Generated
+487 -315
View File
File diff suppressed because it is too large Load Diff
+2 -3
View File
@@ -1,6 +1,6 @@
[tool.poetry]
name = "llama-parse"
version = "0.1.3"
version = "0.3.3"
description = "Parse files into RAG-Optimized formats."
authors = ["Logan Markewich <logan@llamaindex.ai>"]
license = "MIT"
@@ -9,8 +9,7 @@ packages = [{include = "llama_parse"}]
[tool.poetry.dependencies]
python = ">=3.8.1,<4.0"
llama-index = "^0.9.40"
llama-index-core = ">=0.10.7"
[tool.poetry.group.dev.dependencies]
pytest = "^8.0.0"