mirror of
https://github.com/run-llama/llama_cloud_services.git
synced 2026-07-24 23:55:25 -04:00
Compare commits
19 Commits
nprad/add-le
..
list
| Author | SHA1 | Date | |
|---|---|---|---|
| 1ebe1cee67 | |||
| e9252eb48a | |||
| dad7728135 | |||
| c5111e3335 | |||
| bbbdb98362 | |||
| 60cdc2af84 | |||
| 344c20f331 | |||
| 2b0496e947 | |||
| 6c63dba6fb | |||
| 734c021a2e | |||
| eeb034896f | |||
| 4c977e8384 | |||
| c6137713c7 | |||
| fd4b1893f1 | |||
| e542e6136b | |||
| 393451e304 | |||
| 5084ba27ab | |||
| c82771f841 | |||
| dc6860535a |
@@ -14,7 +14,7 @@ env:
|
||||
jobs:
|
||||
build-n-publish:
|
||||
name: Build and publish to PyPI
|
||||
if: github.repository == 'run-llama/llama_parse'
|
||||
if: github.repository == 'run-llama/llama_cloud_services'
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
|
||||
@@ -36,7 +36,7 @@ See the quickstart guides for each service for more information:
|
||||
|
||||
- [LlamaParse](./parse.md)
|
||||
- [LlamaReport (beta/invite-only)](./report.md)
|
||||
- [LlamaExtract (coming soon!)]()
|
||||
- [LlamaExtract (beta/invite-only)](./extract.md)
|
||||
|
||||
## Documentation
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 156 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 85 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 893 KiB |
File diff suppressed because it is too large
Load Diff
@@ -9,16 +9,20 @@ import httpx
|
||||
from pydantic import BaseModel
|
||||
from llama_cloud import (
|
||||
ExtractAgent as CloudExtractAgent,
|
||||
ExtractAgentCreate,
|
||||
ExtractConfig,
|
||||
ExtractJob,
|
||||
ExtractJobCreate,
|
||||
ExtractRun,
|
||||
ExtractSchemaValidateRequest,
|
||||
ExtractAgentUpdate,
|
||||
File,
|
||||
ExtractMode,
|
||||
StatusEnum,
|
||||
Project,
|
||||
ExtractTarget,
|
||||
LlamaExtractSettings,
|
||||
PaginatedExtractRunsResponse,
|
||||
)
|
||||
from llama_cloud.client import AsyncLlamaCloud
|
||||
from llama_cloud_services.extract.utils import JSONObjectType, augment_async_errors
|
||||
@@ -53,6 +57,8 @@ class ExtractionAgent:
|
||||
num_workers: int = 4,
|
||||
show_progress: bool = True,
|
||||
verbose: bool = False,
|
||||
verify: Optional[bool] = True,
|
||||
httpx_timeout: Optional[float] = 60,
|
||||
):
|
||||
self._client = client
|
||||
self._agent = agent
|
||||
@@ -62,6 +68,8 @@ class ExtractionAgent:
|
||||
self.max_timeout = max_timeout
|
||||
self.num_workers = num_workers
|
||||
self.show_progress = show_progress
|
||||
self.verify = verify
|
||||
self.httpx_timeout = httpx_timeout
|
||||
self._verbose = verbose
|
||||
self._data_schema: Union[JSONObjectType, None] = None
|
||||
self._config: Union[ExtractConfig, None] = None
|
||||
@@ -74,14 +82,20 @@ class ExtractionAgent:
|
||||
|
||||
def run_coro() -> T:
|
||||
async def wrapped_coro() -> T:
|
||||
# Get the original client to preserve its configuration
|
||||
original_client = self._client._client_wrapper.httpx_client
|
||||
|
||||
# Create a new client with the same configuration as the original
|
||||
async with httpx.AsyncClient(
|
||||
timeout=self._client._client_wrapper.httpx_client.timeout,
|
||||
verify=self.verify,
|
||||
timeout=self.httpx_timeout,
|
||||
) as client:
|
||||
original_client = self._client._client_wrapper.httpx_client
|
||||
# Temporarily replace the client
|
||||
self._client._client_wrapper.httpx_client = client
|
||||
try:
|
||||
return await coro
|
||||
finally:
|
||||
# Restore the original client
|
||||
self._client._client_wrapper.httpx_client = original_client
|
||||
|
||||
return asyncio.run(wrapped_coro())
|
||||
@@ -114,7 +128,7 @@ class ExtractionAgent:
|
||||
)
|
||||
validated_schema = self._run_in_thread(
|
||||
self._client.llama_extract.validate_extraction_schema(
|
||||
data_schema=processed_schema
|
||||
request=ExtractSchemaValidateRequest(data_schema=processed_schema)
|
||||
)
|
||||
)
|
||||
self._data_schema = validated_schema.data_schema
|
||||
@@ -187,8 +201,10 @@ class ExtractionAgent:
|
||||
self._agent = self._run_in_thread(
|
||||
self._client.llama_extract.update_extraction_agent(
|
||||
extraction_agent_id=self.id,
|
||||
data_schema=self.data_schema,
|
||||
config=self.config,
|
||||
request=ExtractAgentUpdate(
|
||||
data_schema=self.data_schema,
|
||||
config=self.config,
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
@@ -375,15 +391,29 @@ class ExtractionAgent:
|
||||
)
|
||||
)
|
||||
|
||||
def list_extraction_runs(self) -> List[ExtractRun]:
|
||||
def delete_extraction_run(self, run_id: str) -> None:
|
||||
"""Delete an extraction run by ID.
|
||||
|
||||
Args:
|
||||
run_id (str): The ID of the extraction run to delete
|
||||
"""
|
||||
self._run_in_thread(
|
||||
self._client.llama_extract.delete_extraction_run(run_id=run_id)
|
||||
)
|
||||
|
||||
def list_extraction_runs(
|
||||
self, page: int = 0, limit: int = 100
|
||||
) -> PaginatedExtractRunsResponse:
|
||||
"""List extraction runs for the extraction agent.
|
||||
|
||||
Returns:
|
||||
List[ExtractRun]: List of extraction runs
|
||||
PaginatedExtractRunsResponse: Paginated list of extraction runs
|
||||
"""
|
||||
return self._run_in_thread(
|
||||
self._client.llama_extract.list_extract_runs(
|
||||
extraction_agent_id=self.id,
|
||||
skip=page * limit,
|
||||
limit=limit,
|
||||
)
|
||||
)
|
||||
|
||||
@@ -416,6 +446,12 @@ class LlamaExtract(BaseComponent):
|
||||
verbose: bool = Field(
|
||||
default=False, description="Show verbose output when extracting files."
|
||||
)
|
||||
verify: Optional[bool] = Field(
|
||||
default=True, description="Simple SSL verification option."
|
||||
)
|
||||
httpx_timeout: Optional[float] = Field(
|
||||
default=60, description="Timeout for the httpx client."
|
||||
)
|
||||
_async_client: AsyncLlamaCloud = PrivateAttr()
|
||||
_thread_pool: ThreadPoolExecutor = PrivateAttr()
|
||||
_project_id: Optional[str] = PrivateAttr()
|
||||
@@ -431,6 +467,8 @@ class LlamaExtract(BaseComponent):
|
||||
show_progress: bool = True,
|
||||
project_id: Optional[str] = None,
|
||||
organization_id: Optional[str] = None,
|
||||
verify: Optional[bool] = True,
|
||||
httpx_timeout: Optional[float] = 60,
|
||||
verbose: bool = False,
|
||||
):
|
||||
if not api_key:
|
||||
@@ -448,11 +486,18 @@ class LlamaExtract(BaseComponent):
|
||||
max_timeout=max_timeout,
|
||||
num_workers=num_workers,
|
||||
show_progress=show_progress,
|
||||
verify=verify,
|
||||
httpx_timeout=httpx_timeout,
|
||||
verbose=verbose,
|
||||
)
|
||||
self._httpx_client = httpx.AsyncClient(verify=verify, timeout=httpx_timeout)
|
||||
self.verify = verify
|
||||
self.httpx_timeout = httpx_timeout
|
||||
|
||||
self._async_client = AsyncLlamaCloud(
|
||||
token=self.api_key, base_url=self.base_url, timeout=None
|
||||
token=self.api_key,
|
||||
base_url=self.base_url,
|
||||
httpx_client=self._httpx_client,
|
||||
)
|
||||
self._thread_pool = ThreadPoolExecutor(
|
||||
max_workers=min(10, (os.cpu_count() or 1) + 4)
|
||||
@@ -481,17 +526,22 @@ class LlamaExtract(BaseComponent):
|
||||
def run_coro() -> T:
|
||||
# Create a new client for this thread
|
||||
async def wrapped_coro() -> T:
|
||||
assert (
|
||||
self._httpx_client is not None
|
||||
), "httpx_client should be initialized"
|
||||
# Create a new client with the same configuration as the original
|
||||
async with httpx.AsyncClient(
|
||||
timeout=self._async_client._client_wrapper.httpx_client.timeout,
|
||||
verify=self.verify,
|
||||
timeout=self.httpx_timeout,
|
||||
) as client:
|
||||
# Replace the client in the coro's context
|
||||
original_client = self._async_client._client_wrapper.httpx_client
|
||||
# Temporarily replace the client
|
||||
self._async_client._client_wrapper.httpx_client = client
|
||||
try:
|
||||
return await coro
|
||||
finally:
|
||||
# Restore the original client
|
||||
self._async_client._client_wrapper.httpx_client = (
|
||||
original_client
|
||||
self._httpx_client
|
||||
)
|
||||
|
||||
return asyncio.run(wrapped_coro())
|
||||
@@ -526,11 +576,13 @@ class LlamaExtract(BaseComponent):
|
||||
|
||||
agent = self._run_in_thread(
|
||||
self._async_client.llama_extract.create_extraction_agent(
|
||||
name=name,
|
||||
data_schema=data_schema,
|
||||
config=config or DEFAULT_EXTRACT_CONFIG,
|
||||
project_id=self._project_id,
|
||||
organization_id=self._organization_id,
|
||||
request=ExtractAgentCreate(
|
||||
name=name,
|
||||
data_schema=data_schema,
|
||||
config=config or DEFAULT_EXTRACT_CONFIG,
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
@@ -592,6 +644,8 @@ class LlamaExtract(BaseComponent):
|
||||
num_workers=self.num_workers,
|
||||
show_progress=self.show_progress,
|
||||
verbose=self.verbose,
|
||||
verify=self.verify,
|
||||
httpx_timeout=self.httpx_timeout,
|
||||
)
|
||||
|
||||
def list_agents(self) -> List[ExtractionAgent]:
|
||||
|
||||
@@ -111,6 +111,10 @@ class LlamaParse(BasePydanticReader):
|
||||
)
|
||||
|
||||
# Parsing specific configurations (Alphabetical order)
|
||||
adaptive_long_table: Optional[bool] = Field(
|
||||
default=False,
|
||||
description="If set to true, LlamaParse will try to detect long table and adapt the output.",
|
||||
)
|
||||
annotate_links: Optional[bool] = Field(
|
||||
default=False,
|
||||
description="Annotate links found in the document to extract their URL.",
|
||||
@@ -163,14 +167,7 @@ class LlamaParse(BasePydanticReader):
|
||||
default=None,
|
||||
description="The top margin of the bounding box to use to extract text from documents expressed as a float between 0 and 1 representing the percentage of the page height.",
|
||||
)
|
||||
complemental_formatting_instruction: Optional[str] = Field(
|
||||
default=None,
|
||||
description="The complemental formatting instruction for the parser. Tell llamaParse how some thing should to be formatted, while retaining the markdown output.",
|
||||
)
|
||||
content_guideline_instruction: Optional[str] = Field(
|
||||
default=None,
|
||||
description="The content guideline for the parser. Tell LlamaParse how the content should be changed / transformed.",
|
||||
)
|
||||
|
||||
continuous_mode: Optional[bool] = Field(
|
||||
default=False,
|
||||
description="Parse documents continuously, leading to better results on documents where tables span across two pages.",
|
||||
@@ -203,10 +200,7 @@ class LlamaParse(BasePydanticReader):
|
||||
default=False,
|
||||
description="Note: Non compatible with gpt-4o. If set to true, the parser will use a faster mode to extract text from documents. This mode will skip OCR of images, and table/heading reconstruction.",
|
||||
)
|
||||
formatting_instruction: Optional[str] = Field(
|
||||
default=None,
|
||||
description="The Formatting instruction for the parser. Override default llamaParse behavior. In most case you want to use complemental_formatting_instruction instead.",
|
||||
)
|
||||
|
||||
guess_xlsx_sheet_names: Optional[bool] = Field(
|
||||
default=False,
|
||||
description="Whether to guess the sheet names of the xlsx file.",
|
||||
@@ -282,10 +276,18 @@ class LlamaParse(BasePydanticReader):
|
||||
default=None,
|
||||
description="A templated suffix to add to the beginning of each page. If it contain `{page_number}`, it will be replaced by the page number.",
|
||||
)
|
||||
parse_mode: Optional[str] = Field(
|
||||
default=None,
|
||||
description="The parsing mode to use, see ParsingMode enum for possible values ",
|
||||
)
|
||||
premium_mode: Optional[bool] = Field(
|
||||
default=False,
|
||||
description="Use our best parser mode if set to True.",
|
||||
)
|
||||
preserve_layout_alignment_across_pages: Optional[bool] = Field(
|
||||
default=False,
|
||||
description="Preserve grid alignment across page in text mode.",
|
||||
)
|
||||
skip_diagonal_text: Optional[bool] = Field(
|
||||
default=False,
|
||||
description="If set to true, the parser will ignore diagonal text (when the text rotation in degrees modulo 90 is not 0).",
|
||||
@@ -327,6 +329,14 @@ class LlamaParse(BasePydanticReader):
|
||||
default=None,
|
||||
description="The named JSON Schema to use to structure the output of the parsing job. For convenience / testing, LlamaParse provides a few named JSON Schema that can be used directly. Use 'imFeelingLucky' to let llamaParse dream the schema.",
|
||||
)
|
||||
system_prompt: Optional[str] = Field(
|
||||
default=None,
|
||||
description="The system prompt. Replace llamaParse default system prompt, may impact accuracy",
|
||||
)
|
||||
system_prompt_append: Optional[str] = Field(
|
||||
default=None,
|
||||
description="String to append to default system prompt.",
|
||||
)
|
||||
take_screenshot: Optional[bool] = Field(
|
||||
default=False,
|
||||
description="Whether to take screenshot of each page of the document.",
|
||||
@@ -335,9 +345,9 @@ class LlamaParse(BasePydanticReader):
|
||||
default=None,
|
||||
description="The target pages to extract text from documents. Describe as a comma separated list of page numbers. The first page of the document is page 0",
|
||||
)
|
||||
use_vendor_multimodal_model: Optional[bool] = Field(
|
||||
default=False,
|
||||
description="Whether to use the vendor multimodal API.",
|
||||
user_prompt: Optional[str] = Field(
|
||||
default=None,
|
||||
description="The user prompt. Replace llamaParse default user prompt",
|
||||
)
|
||||
vendor_multimodal_api_key: Optional[str] = Field(
|
||||
default=None,
|
||||
@@ -357,6 +367,18 @@ class LlamaParse(BasePydanticReader):
|
||||
default=None,
|
||||
description="The bounding box to use to extract text from documents describe as a string containing the bounding box margins",
|
||||
)
|
||||
complemental_formatting_instruction: Optional[str] = Field(
|
||||
default=None,
|
||||
description="The complemental formatting instruction for the parser. Tell llamaParse how some thing should to be formatted, while retaining the markdown output.",
|
||||
)
|
||||
content_guideline_instruction: Optional[str] = Field(
|
||||
default=None,
|
||||
description="The content guideline for the parser. Tell LlamaParse how the content should be changed / transformed.",
|
||||
)
|
||||
formatting_instruction: Optional[str] = Field(
|
||||
default=None,
|
||||
description="The Formatting instruction for the parser. Override default llamaParse behavior. In most case you want to use complemental_formatting_instruction instead.",
|
||||
)
|
||||
gpt4o_mode: Optional[bool] = Field(
|
||||
default=False,
|
||||
description="Whether to use gpt-4o extract text from documents.",
|
||||
@@ -373,6 +395,11 @@ class LlamaParse(BasePydanticReader):
|
||||
default="", description="The parsing instruction for the parser."
|
||||
)
|
||||
|
||||
use_vendor_multimodal_model: Optional[bool] = Field(
|
||||
default=False,
|
||||
description="Whether to use the vendor multimodal API.",
|
||||
)
|
||||
|
||||
@field_validator("api_key", mode="before", check_fields=True)
|
||||
@classmethod
|
||||
def validate_api_key(cls, v: str) -> str:
|
||||
@@ -501,6 +528,9 @@ class LlamaParse(BasePydanticReader):
|
||||
|
||||
data["from_python_package"] = True
|
||||
|
||||
if self.adaptive_long_table:
|
||||
data["adaptive_long_table"] = self.adaptive_long_table
|
||||
|
||||
if self.annotate_links:
|
||||
data["annotate_links"] = self.annotate_links
|
||||
|
||||
@@ -552,11 +582,17 @@ class LlamaParse(BasePydanticReader):
|
||||
data["bbox_top"] = self.bbox_top
|
||||
|
||||
if self.complemental_formatting_instruction:
|
||||
print(
|
||||
"WARNING: complemental_formatting_instruction is deprecated and may be remove in a future release. Use system_prompt, system_prompt_append or user_prompt instead."
|
||||
)
|
||||
data[
|
||||
"complemental_formatting_instruction"
|
||||
] = self.complemental_formatting_instruction
|
||||
|
||||
if self.content_guideline_instruction:
|
||||
print(
|
||||
"WARNING: content_guideline_instruction is deprecated and may be remove in a future release. Use system_prompt, system_prompt_append or user_prompt instead."
|
||||
)
|
||||
data["content_guideline_instruction"] = self.content_guideline_instruction
|
||||
|
||||
if self.continuous_mode:
|
||||
@@ -584,6 +620,9 @@ class LlamaParse(BasePydanticReader):
|
||||
data["fast_mode"] = self.fast_mode
|
||||
|
||||
if self.formatting_instruction:
|
||||
print(
|
||||
"WARNING: formatting_instruction is deprecated and may be remove in a future release. Use system_prompt, system_prompt_append or user_prompt instead."
|
||||
)
|
||||
data["formatting_instruction"] = self.formatting_instruction
|
||||
|
||||
if self.guess_xlsx_sheet_names:
|
||||
@@ -623,6 +662,9 @@ class LlamaParse(BasePydanticReader):
|
||||
data["invalidate_cache"] = self.invalidate_cache
|
||||
|
||||
if self.is_formatting_instruction:
|
||||
print(
|
||||
"WARNING: formatting_instruction is deprecated and may be remove in a future release. Use system_prompt, system_prompt_append or user_prompt instead."
|
||||
)
|
||||
data["is_formatting_instruction"] = self.is_formatting_instruction
|
||||
|
||||
if self.job_timeout_extra_time_per_page_in_seconds is not None:
|
||||
@@ -664,13 +706,21 @@ class LlamaParse(BasePydanticReader):
|
||||
|
||||
if self.parsing_instruction:
|
||||
print(
|
||||
"WARNING: parsing_instruction is deprecated. Use complemental_formatting_instruction or content_guideline_instruction instead."
|
||||
"WARNING: parsing_instruction is deprecated. Use system_prompt, system_prompt_append or user_prompt instead."
|
||||
)
|
||||
data["parsing_instruction"] = self.parsing_instruction
|
||||
|
||||
if self.parse_mode:
|
||||
data["parse_mode"] = self.parse_mode
|
||||
|
||||
if self.premium_mode:
|
||||
data["premium_mode"] = self.premium_mode
|
||||
|
||||
if self.preserve_layout_alignment_across_pages:
|
||||
data[
|
||||
"preserve_layout_alignment_across_pages"
|
||||
] = self.preserve_layout_alignment_across_pages
|
||||
|
||||
if self.skip_diagonal_text:
|
||||
data["skip_diagonal_text"] = self.skip_diagonal_text
|
||||
|
||||
@@ -699,13 +749,17 @@ class LlamaParse(BasePydanticReader):
|
||||
data[
|
||||
"structured_output_json_schema_name"
|
||||
] = self.structured_output_json_schema_name
|
||||
|
||||
if self.system_prompt is not None:
|
||||
data["system_prompt"] = self.system_prompt
|
||||
if self.system_prompt_append is not None:
|
||||
data["system_prompt_append"] = self.system_prompt_append
|
||||
if self.take_screenshot:
|
||||
data["take_screenshot"] = self.take_screenshot
|
||||
|
||||
if self.target_pages is not None:
|
||||
data["target_pages"] = self.target_pages
|
||||
|
||||
if self.user_prompt is not None:
|
||||
data["user_prompt"] = self.user_prompt
|
||||
if self.use_vendor_multimodal_model:
|
||||
data["use_vendor_multimodal_model"] = self.use_vendor_multimodal_model
|
||||
|
||||
|
||||
@@ -14,6 +14,16 @@ class ResultType(str, Enum):
|
||||
STRUCTURED = "structured"
|
||||
|
||||
|
||||
class ParsingMode(str, Enum):
|
||||
"""The parsing mode for the parser."""
|
||||
|
||||
parse_page_without_llm = "parse_page_without_llm"
|
||||
parse_page_with_llm = "parse_page_with_llm"
|
||||
parse_page_with_lvm = "parse_page_with_lvm"
|
||||
parse_page_with_agent = "parse_page_with_agent"
|
||||
parse_document_with_llm = "parse_document_with_llm"
|
||||
|
||||
|
||||
class Language(str, Enum):
|
||||
BAZA = "abq"
|
||||
ADYGHE = "ady"
|
||||
|
||||
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
|
||||
|
||||
[tool.poetry]
|
||||
name = "llama-parse"
|
||||
version = "0.6.1"
|
||||
version = "0.6.8"
|
||||
description = "Parse files into RAG-Optimized formats."
|
||||
authors = ["Logan Markewich <logan@llamaindex.ai>"]
|
||||
license = "MIT"
|
||||
@@ -13,7 +13,7 @@ packages = [{include = "llama_parse"}]
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = ">=3.9,<4.0"
|
||||
llama-cloud-services = ">=0.6.1"
|
||||
llama-cloud-services = ">=0.6.7"
|
||||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
pytest = "^8.0.0"
|
||||
|
||||
Generated
+961
-955
File diff suppressed because it is too large
Load Diff
+2
-2
@@ -8,7 +8,7 @@ python_version = "3.10"
|
||||
|
||||
[tool.poetry]
|
||||
name = "llama-cloud-services"
|
||||
version = "0.6.1"
|
||||
version = "0.6.8"
|
||||
description = "Tailored SDK clients for LlamaCloud services."
|
||||
authors = ["Logan Markewich <logan@runllama.ai>"]
|
||||
license = "MIT"
|
||||
@@ -18,7 +18,7 @@ packages = [{include = "llama_cloud_services"}]
|
||||
[tool.poetry.dependencies]
|
||||
python = ">=3.9,<4.0"
|
||||
llama-index-core = ">=0.11.0"
|
||||
llama-cloud = "^0.1.11"
|
||||
llama-cloud = "^0.1.16"
|
||||
pydantic = "!=2.10"
|
||||
click = "^8.1.7"
|
||||
python-dotenv = "^1.0.1"
|
||||
|
||||
@@ -182,7 +182,14 @@ class TestExtractionAgent:
|
||||
assert "new_field" in updated_agent.data_schema["properties"]
|
||||
|
||||
def test_list_extraction_runs(self, test_agent: ExtractionAgent):
|
||||
assert len(test_agent.list_extraction_runs()) == 0
|
||||
assert test_agent.list_extraction_runs().total == 0
|
||||
test_agent.extract(TEST_PDF)
|
||||
runs = test_agent.list_extraction_runs()
|
||||
assert len(runs) > 0
|
||||
assert runs.total > 0
|
||||
|
||||
def test_delete_extraction_run(self, test_agent: ExtractionAgent):
|
||||
assert test_agent.list_extraction_runs().total == 0
|
||||
run = test_agent.extract(TEST_PDF)
|
||||
test_agent.delete_extraction_run(run.id)
|
||||
runs = test_agent.list_extraction_runs()
|
||||
assert runs.total == 0
|
||||
|
||||
@@ -81,6 +81,11 @@ async def test_create_and_delete_report(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.xfail(
|
||||
condition=lambda: os.getenv("CI"),
|
||||
reason="Report plan sometimes times out",
|
||||
raises=TimeoutError,
|
||||
)
|
||||
async def test_report_plan_workflow(report: ReportClient) -> None:
|
||||
"""Test the report planning workflow."""
|
||||
# Wait for the plan
|
||||
|
||||
Reference in New Issue
Block a user