Compare commits

..

7 Commits

Author SHA1 Message Date
Logan Markewich 25d16864ea fix publishing 2025-12-10 11:48:28 -06:00
Logan Markewich 1d3a93a6c5 fix publishing by removing generate from build command 2025-12-10 11:47:37 -06:00
Clelia (Astra) Bertelli 18dd04b6de docs: correct links in readme (#1056) 2025-12-10 17:08:58 +01:00
github-actions[bot] 685a5e6ccc chore: version packages (#1054) 2025-12-09 15:30:13 -06:00
Jim Geurts 576c3d9076 feat: support zod v4 & v3 (#1052) 2025-12-09 15:29:23 -06:00
Logan c8321d2bc5 improve parse ts polling (#1053) 2025-12-09 15:21:19 -06:00
Tuana Çelik 131bbed7aa batch parse sctript with asyncio (#1051)
* batch parse sctript with asyncio

* lint

---------

Co-authored-by: Logan Markewich <logan.markewich@live.com>
2025-12-08 18:50:11 +01:00
12 changed files with 216 additions and 3354 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"llama-cloud-services": patch
---
Fix publishing
+1 -1
View File
@@ -398,6 +398,6 @@ Another option (orthogonal to the above) is to break the document into smaller s
## Additional Resources
- [Extract Documentation](https://docs.cloud.llamaindex.ai/llamaextract/getting_started) - Details on Extract features, API and examples.
- [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
- [Example Application with TypeScript](./examples-ts/extract/) - End-to-end examples using LlamaExtract TypeScript client.
- [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
+48 -3260
View File
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -146,9 +146,9 @@ 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)
- [Getting Started](../../examples/parse/demo_basic.ipynb)
- [Advanced RAG Example](../../examples/parse/demo_advanced.ipynb)
- [Raw API Usage](../../examples/parse/demo_api.ipynb)
## Documentation
+15
View File
@@ -1,5 +1,20 @@
# llama-cloud-services
## 0.5.0
### Minor Changes
- 576c3d9: feat: support zod v4 & v3
Adds support for zod v4 while maintaining backward compatibility with v3.
- Updated zod peer dependency to accept both v3 and v4: `^3.25.76 || ^4.0.0`
- Migrated all import statements to use `zod/v4` import path for compatibility
### Patch Changes
- c8321d2: Improve parse results polling
- 576c3d9: Support zod v3 an v4
## 0.4.3
### Patch Changes
+9 -8
View File
@@ -1,12 +1,12 @@
{
"name": "llama-cloud-services",
"version": "0.4.3",
"version": "0.5.0",
"type": "module",
"license": "MIT",
"scripts": {
"get-openapi": "node ./scripts/get-openapi.js",
"generate": "./node_modules/.bin/openapi-ts",
"build": "pnpm run generate && bunchee",
"build": "bunchee",
"dev": "bunchee --watch",
"lint": "eslint src/ --ignore-pattern client/*.ts --no-warn-ignored",
"format": "prettier --write ./src/ tests/",
@@ -116,9 +116,9 @@
"@eslint/js": "^9.32.0",
"@hey-api/client-fetch": "^0.10.1",
"@hey-api/openapi-ts": "^0.67.5",
"@llamaindex/core": "^0.6.19",
"@llamaindex/core": "^0.6.22",
"@llamaindex/env": "^0.1.30",
"@llamaindex/workflow-core": "^0.4.1",
"@llamaindex/workflow-core": "^1.3.3",
"@types/node": "^20.19.9",
"@typescript-eslint/eslint-plugin": "^8.38.0",
"@typescript-eslint/parser": "^8.38.0",
@@ -131,18 +131,19 @@
"turbo": "^2.5.5",
"typescript": "^5.8.3",
"typescript-eslint": "^8.38.0",
"vitest": "^2.0.0"
"vitest": "^2.0.0",
"zod": "^4.1.13"
},
"peerDependencies": {
"@llamaindex/core": "^0.6.19",
"@llamaindex/env": "^0.1.30",
"@llamaindex/workflow-core": "^0.4.1"
"@llamaindex/workflow-core": "^1.3.3",
"zod": "^3.25.0 || ^4.0.0"
},
"dependencies": {
"ajv": "^8.17.1",
"file-type": "^21.0.0",
"p-retry": "^6.2.1",
"zod": "^3.25.76"
"p-retry": "^6.2.1"
},
"packageManager": "pnpm@10.8.1"
}
@@ -1,6 +1,6 @@
// This file is auto-generated by @hey-api/openapi-ts
import { z } from "zod";
import { z } from "zod/v4";
export const zNoneSegmentationConfig = z.object({
mode: z.literal("none").optional().default("none"),
@@ -770,7 +770,7 @@ export const zMetadataFilter = z.object({
export const zFilterCondition: z.ZodTypeAny = z.enum(["and", "or", "not"]);
export const zMetadataFilters: z.AnyZodObject = z.object({
export const zMetadataFilters: z.ZodObject<z.ZodRawShape> = z.object({
filters: z.array(z.unknown()),
condition: z.union([zFilterCondition, z.null()]).optional(),
});
@@ -782,7 +782,7 @@ export const zRetrievalMode: z.ZodTypeAny = z.enum([
"auto_routed",
]);
export const zPresetRetrievalParams: z.AnyZodObject = z.object({
export const zPresetRetrievalParams: z.ZodObject<z.ZodRawShape> = z.object({
dense_similarity_top_k: z
.union([z.number().int().gte(1).lte(100), z.null()])
.optional(),
@@ -825,7 +825,7 @@ export const zSupportedLlmModelNames: z.ZodTypeAny = z.enum([
"VERTEX_AI_CLAUDE_3_5_SONNET_V2",
]);
export const zLlmParameters: z.AnyZodObject = z.object({
export const zLlmParameters: z.ZodObject<z.ZodRawShape> = z.object({
model_name: zSupportedLlmModelNames.optional(),
system_prompt: z.union([z.string().max(3000), z.null()]).optional(),
temperature: z.union([z.number(), z.null()]).optional(),
@@ -834,7 +834,7 @@ export const zLlmParameters: z.AnyZodObject = z.object({
class_name: z.string().optional().default("base_component"),
});
export const zChatData: z.AnyZodObject = z.object({
export const zChatData: z.ZodObject<z.ZodRawShape> = z.object({
retrieval_parameters: zPresetRetrievalParams.optional(),
llm_parameters: z.union([zLlmParameters, z.null()]).optional(),
class_name: z.string().optional().default("base_component"),
@@ -2141,7 +2141,7 @@ export const zTextItem = z.object({
value: z.string(),
});
export const zListItem: z.AnyZodObject = z.object({
export const zListItem: z.ZodObject<z.ZodRawShape> = z.object({
type: z.literal("list").optional().default("list"),
bBox: z.union([z.unknown(), z.null()]).optional(),
items: z.array(z.unknown()),
+1 -1
View File
@@ -1,6 +1,6 @@
import { workflowEvent } from "@llamaindex/workflow-core";
import { zodEvent } from "@llamaindex/workflow-core/util/zod";
import { z } from "zod";
import { z } from "zod/v4";
import { parseFormSchema } from "./schema";
export const uploadEvent = zodEvent(
+2 -4
View File
@@ -2,7 +2,7 @@ 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";
import { z } from "zod/v4";
const DEFAULT_NAME = "llama_cloud_index_tool";
const DEFAULT_DESCRIPTION =
@@ -21,9 +21,7 @@ export function createQueryEngineTool(
name: metadata?.name ?? DEFAULT_NAME,
description: metadata?.description ?? DEFAULT_DESCRIPTION,
parameters: z.object({
query: z.string({
description: "The query to search for",
}),
query: z.string().describe("The query to search for"),
}),
execute: async ({ query }) => {
const response = await queryEngine.query({ query });
+113 -59
View File
@@ -1,9 +1,10 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { type Client, createClient, createConfig } from "@hey-api/client-fetch";
import { type FailedAttemptError } from "p-retry";
import { Document, FileReader } from "@llamaindex/core/schema";
import { fs, getEnv, path } from "@llamaindex/env";
import {
type BodyUploadFileApiParsingUploadPost,
type BodyUploadFileApiV1ParsingUploadPost,
type FailPageMode,
type ParserLanguages,
type ParsingMode,
@@ -32,6 +33,33 @@ type WriteStream = {
// eslint-disable-next-line no-var
var process: any;
function handleFailedAttempt(
error: FailedAttemptError,
jobId: string,
verbose: boolean,
) {
// Retry only on 5XX or socket errors.
const status = (error.cause as any)?.response?.status;
if (
!(
(status && status >= 500 && status < 600) ||
((error.cause as any)?.code &&
((error.cause as any).code === "ECONNRESET" ||
(error.cause as any).code === "ETIMEDOUT" ||
(error.cause as any).code === "ECONNREFUSED")) ||
(status && status === 404)
)
) {
throw error;
}
if (verbose) {
console.warn(
`Attempting to get job ${jobId} result (attempt ${error.attemptNumber}) failed. Retrying...`,
);
}
}
/**
* Represents a reader for parsing files using the LlamaParse API.
* See https://github.com/run-llama/llama_parse
@@ -188,6 +216,16 @@ export class LlamaParseReader extends FileReader {
extract_printed_page_number?: boolean | undefined;
tier?: string | undefined;
version?: string | undefined;
layout_aware?: boolean | undefined;
line_level_bounding_box?: boolean | undefined;
specialized_image_parsing?: boolean | undefined;
aggressive_table_extraction?: boolean | undefined;
preserve_very_small_text?: boolean | undefined;
spreadsheet_force_formula_computation?: boolean | undefined;
inline_images_in_markdown?: boolean | undefined;
keep_page_separator_when_merging_tables?: boolean | undefined;
remove_hidden_text?: boolean | undefined;
presentation_out_of_bounds_content?: boolean | undefined;
constructor(
params: Partial<Omit<LlamaParseReader, "language" | "apiKey">> & {
@@ -387,11 +425,25 @@ export class LlamaParseReader extends FileReader {
extract_printed_page_number: this.extract_printed_page_number,
tier: this.tier,
version: this.version,
layout_aware: this.layout_aware,
line_level_bounding_box: this.line_level_bounding_box,
specialized_image_parsing: this.specialized_image_parsing,
aggressive_table_extraction: this.aggressive_table_extraction,
preserve_very_small_text: this.preserve_very_small_text,
spreadsheet_force_formula_computation:
this.spreadsheet_force_formula_computation,
inline_images_in_markdown: this.inline_images_in_markdown,
webhook_configurations: undefined,
keep_page_separator_when_merging_tables:
this.keep_page_separator_when_merging_tables,
remove_hidden_text: this.remove_hidden_text,
presentation_out_of_bounds_content:
this.presentation_out_of_bounds_content,
} satisfies {
[Key in keyof BodyUploadFileApiParsingUploadPost]-?:
| BodyUploadFileApiParsingUploadPost[Key]
[Key in keyof BodyUploadFileApiV1ParsingUploadPost]-?:
| BodyUploadFileApiV1ParsingUploadPost[Key]
| undefined;
} as unknown as BodyUploadFileApiParsingUploadPost;
} as unknown as BodyUploadFileApiV1ParsingUploadPost;
const response = await uploadFileApiV1ParsingUploadPost({
client: this.#client,
@@ -443,26 +495,8 @@ export class LlamaParseReader extends FileReader {
}),
{
retries: this.maxErrorCount,
onFailedAttempt: (error) => {
// Retry only on 5XX or socket errors.
const status = (error.cause as any)?.response?.status;
if (
!(
(status && status >= 500 && status < 600) ||
((error.cause as any)?.code &&
((error.cause as any).code === "ECONNRESET" ||
(error.cause as any).code === "ETIMEDOUT" ||
(error.cause as any).code === "ECONNREFUSED"))
)
) {
throw error;
}
if (this.verbose) {
console.warn(
`Attempting to get job ${jobId} result (attempt ${error.attemptNumber}) failed. Retrying...`,
);
}
},
onFailedAttempt: (error) =>
handleFailedAttempt(error, jobId, this.verbose),
},
);
} catch (e: any) {
@@ -475,49 +509,69 @@ export class LlamaParseReader extends FileReader {
const status = (data as Record<string, unknown>)["status"];
if (status === "SUCCESS") {
let resultData;
switch (resultType) {
case "json": {
resultData =
await getJobJsonResultApiV1ParsingJobJobIdResultJsonGet({
client: this.#client,
throwOnError: true,
path: { job_id: jobId },
query: {
organization_id: this.organization_id ?? null,
},
signal: AbortSignal.timeout(this.maxTimeout * 1000),
});
break;
const resultData = await pRetry(
() =>
getJobJsonResultApiV1ParsingJobJobIdResultJsonGet({
client: this.#client,
throwOnError: true,
path: { job_id: jobId },
query: {
organization_id: this.organization_id ?? null,
},
signal: AbortSignal.timeout(this.maxTimeout * 1000),
}),
{
retries: this.maxErrorCount,
onFailedAttempt: (error) =>
handleFailedAttempt(error, jobId, this.verbose),
},
);
return resultData.data;
}
case "markdown": {
resultData =
await getJobResultApiV1ParsingJobJobIdResultMarkdownGet({
client: this.#client,
throwOnError: true,
path: { job_id: jobId },
query: {
organization_id: this.organization_id ?? null,
},
signal: AbortSignal.timeout(this.maxTimeout * 1000),
});
break;
const resultData = await pRetry(
() =>
getJobResultApiV1ParsingJobJobIdResultMarkdownGet({
client: this.#client,
throwOnError: true,
path: { job_id: jobId },
query: {
organization_id: this.organization_id ?? null,
},
signal: AbortSignal.timeout(this.maxTimeout * 1000),
}),
{
retries: this.maxErrorCount,
onFailedAttempt: (error) =>
handleFailedAttempt(error, jobId, this.verbose),
},
);
return resultData.data;
}
case "text": {
resultData =
await getJobTextResultApiV1ParsingJobJobIdResultTextGet({
client: this.#client,
throwOnError: true,
path: { job_id: jobId },
query: {
organization_id: this.organization_id ?? null,
},
signal: AbortSignal.timeout(this.maxTimeout * 1000),
});
break;
const resultData = await pRetry(
() =>
getJobTextResultApiV1ParsingJobJobIdResultTextGet({
client: this.#client,
throwOnError: true,
path: { job_id: jobId },
query: {
organization_id: this.organization_id ?? null,
},
signal: AbortSignal.timeout(this.maxTimeout * 1000),
}),
{
retries: this.maxErrorCount,
onFailedAttempt: (error) =>
handleFailedAttempt(error, jobId, this.verbose),
},
);
return resultData.data;
}
}
return resultData.data;
} else if (status === "PENDING") {
if (this.verbose && tries % 10 === 0) {
this.stdout?.write(".");
+8 -7
View File
@@ -1,6 +1,6 @@
import { FailPageMode, ParserLanguages, ParsingMode } from "./client";
import { z } from "zod";
import { z } from "zod/v4";
type Language = ParserLanguages;
const VALUES: [Language, ...Language[]] = [
@@ -52,9 +52,10 @@ export const parseFormSchema = z.object({
html_remove_navigation_elements: z.boolean().optional(),
http_proxy: z
.string()
.url(
'Set a valid URL for the HTTP proxy, e.g., "http://proxy.example.com:8080"',
)
.url({
error:
'Set a valid URL for the HTTP proxy, e.g., "http://proxy.example.com:8080"',
})
.refine(
(url) => {
try {
@@ -67,7 +68,7 @@ export const parseFormSchema = z.object({
}
},
{
message: "Invalid HTTP proxy URL",
error: "Invalid HTTP proxy URL",
},
)
.optional(),
@@ -100,7 +101,7 @@ export const parseFormSchema = z.object({
vendor_multimodal_model_name: z.string().optional(),
model: z.string().optional(),
webhook_url: z.string().url().optional(),
parse_mode: z.nativeEnum(ParsingMode).nullable().optional(),
parse_mode: z.enum(ParsingMode).nullable().optional(),
system_prompt: z.string().optional(),
system_prompt_append: z.string().optional(),
user_prompt: z.string().optional(),
@@ -129,7 +130,7 @@ export const parseFormSchema = z.object({
compact_markdown_table: z.boolean().optional(),
markdown_table_multiline_header_separator: z.string().optional(),
page_error_tolerance: z.number().min(0).max(1).optional(),
replace_failed_page_mode: z.nativeEnum(FailPageMode).nullable().optional(),
replace_failed_page_mode: z.enum(FailPageMode).nullable().optional(),
replace_failed_page_with_error_message_prefix: z.string().optional(),
replace_failed_page_with_error_message_suffix: z.string().optional(),
});