Compare commits

..

4 Commits

Author SHA1 Message Date
George He defb9e3ecb Surface parse errors 2025-08-26 12:16:31 -07:00
Adrian Lyjak 37393b7e98 fix: Make env based api url overrideable (#881) 2025-08-20 20:51:09 -06:00
Jerry Liu ecd859a67c fix preset notebook: give outputs in markdown (#883) 2025-08-20 20:50:11 -06:00
Logan decca8e671 update all example notebooks (#882) 2025-08-20 20:49:53 -06:00
6 changed files with 244 additions and 381 deletions
+145 -349
View File
@@ -168,7 +168,49 @@
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Parsing Apple 10-K with Cost-Effective Mode...\n",
"Started parsing the file under job_id 2b27d681-7ea2-42c6-8925-4276c02a7efa\n",
"Number of pages extracted: 82\n",
"\n",
"=== Sample Output - Page 32 (Cost-Effective Mode) ===\n",
"Apple Inc.\n",
"# CONSOLIDATED STATEMENTS OF OPERATIONS\n",
"\n",
"(In millions, except number of shares which are reflected in thousands and per share amounts)\n",
"\n",
"| | Years ended | September 25, 2021 | September 26, 2020 | September 28, 2019 |\n",
"| -------------------------------------------- | ----------------------------------- | ------------------ | ------------------ | ------------------ |\n",
"| Net sales: | Products | $297,392 | $220,747 | $213,883 |\n",
"| | Services | $68,425 | $53,768 | $46,291 |\n",
"| | Total net sales | $365,817 | $274,515 | $260,174 |\n",
"| Cost of sales: | Products | $192,266 | $151,286 | $144,996 |\n",
"| | Services | $20,715 | $18,273 | $16,786 |\n",
"| | Total cost of sales | $212,981 | $169,559 | $161,782 |\n",
"| | Gross margin | $152,836 | $104,956 | $98,392 |\n",
"| Operating expenses: | Research and development | $21,914 | $18,752 | $16,217 |\n",
"| | Selling, general and administrative | $21,973 | $19,916 | $18,245 |\n",
"| | Total operating expenses | $43,887 | $38,668 | $34,462 |\n",
"| Operating income | | $108,949 | $66,288 | $63,930 |\n",
"| Other income/(expense), net | | $258 | $803 | $1,807 |\n",
"| Income before provision for income taxes | | $109,207 | $67,091 | $65,737 |\n",
"| Provision for income taxes | | $14,527 | $9,680 | $10,481 |\n",
"| Net income | | $94,680 | $57,411 | $55,256 |\n",
"| Earnings per share: | Basic | $5.67 | $3.31 | $2.99 |\n",
"| | Diluted | $5.61 | $3.28 | $2.97 |\n",
"| Shares used in computing earnings per share: | Basic | 16,701,272 | 17,352,119 | 18,471,336 |\n",
"| | Diluted | 16,864,919 | 17,528,214 | 18,595,651 |\n",
"\n",
"See accompanying Notes to Consolidated Financial Statements.\n",
"\n",
"Apple Inc. | 2021 Form 10-K | 29\n"
]
}
],
"source": [
"# Parse the Apple 10-K document\n",
"print(\"Parsing Apple 10-K with Cost-Effective Mode...\")\n",
@@ -247,151 +289,44 @@
"output_type": "stream",
"text": [
"Parsing GenAI Research Report with Agentic Mode...\n",
"Started parsing the file under job_id 98d363fb-135f-4529-94a5-713f9b6b2025\n",
"Number of pages extracted: 38\n",
"Started parsing the file under job_id 3bef1c04-e18c-40d5-bc99-512ce045f035\n",
".Number of pages extracted: 38\n",
"\n",
"=== Sample Output - Page 7 (Agentic Mode) ===\n",
"\n",
"# Only one in 10 businesses has undergone the preparation needed to comply with current and upcoming regulations concerning GenAI.\n",
"Only one in 10 businesses has undergone the preparation needed to comply with current and upcoming regulations concerning GenAI. \n",
"The majority of organizations lack a comprehensive governance framework for both AI and GenAI (seven in 10 adopters admit to this).\n",
"\n",
"# The majority of organizations lack a comprehensive governance framework for both AI and GenAI (seven in 10 adopters admit to this).\n",
"| How prepared is your organization to comply with current and upcoming regulations concerning GenAI? | How prepared is your organization to comply with current and upcoming regulations concerning GenAI? | How prepared is your organization to comply with current and upcoming regulations concerning GenAI? | How prepared is your organization to comply with current and upcoming regulations concerning GenAI? | How prepared is your organization to comply with current and upcoming regulations concerning GenAI? |\n",
"| --------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |\n",
"| Fully prepared | 10% (All respondents using/planning to use GenAI) | 35% (Using GenAI and have fully implemented it) | 11% (Using GenAI but haven't yet fully implemented it) | 3% (Not yet using GenAI but intend to within the next two years) |\n",
"| Moderately prepared | 48% | 49% | 66% | 28% |\n",
"| Slightly prepared | 40% | 15% | 23% | 64% |\n",
"| Not prepared | 2% | 0% | 0% | 5% |\n",
"\n",
"## How prepared is your organization to comply with current and upcoming regulations concerning GenAI?\n",
"\n",
"<table>\n",
" <thead>\n",
" <tr>\n",
" <th></th>\n",
" <th>Fully prepared</th>\n",
" <th>Moderately prepared</th>\n",
" <th>Slightly prepared</th>\n",
" <th>Not prepared</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <td>All respondents using/planning to use GenAI</td>\n",
" <td>10%</td>\n",
" <td>48%</td>\n",
" <td>40%</td>\n",
" <td>2%</td>\n",
" </tr>\n",
"<tr>\n",
" <td>Using GenAI and have fully implemented it</td>\n",
" <td>35%</td>\n",
" <td>49%</td>\n",
" <td>15%</td>\n",
" <td>0%</td>\n",
" </tr>\n",
"<tr>\n",
" <td>Using GenAI but haven't yet fully implemented it</td>\n",
" <td>11%</td>\n",
" <td>66%</td>\n",
" <td>23%</td>\n",
" <td>0%</td>\n",
" </tr>\n",
"<tr>\n",
" <td>Not yet using GenAI but intend to within the next two years</td>\n",
" <td>3%</td>\n",
" <td>28%</td>\n",
" <td>64%</td>\n",
" <td>5%</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p><i>Please note that percentages on charts may not add to 100% due to rounding</i></p>\n",
"\n",
"> *Please note that percentages on charts may not add to 100% due to rounding*\n",
"| How would you describe your current GenAI/AI governance framework? | How would you describe your current GenAI/AI governance framework? | How would you describe your current GenAI/AI governance framework? | How would you describe your current GenAI/AI governance framework? | How would you describe your current GenAI/AI governance framework? |\n",
"| ------------------------------------------------------------------ | ------------------------------------------------------------------ | ------------------------------------------------------------------ | ------------------------------------------------------------------ | ------------------------------------------------------------------ |\n",
"| Artificial Intelligence (AI) Governance framework | | | | |\n",
"| Well-established and comprehensive | 13% (All respondents using/planning to use GenAI) | 33% (Using GenAI and have fully implemented it) | 18% (Using GenAI but haven't yet fully implemented it) | 1% (Not yet using GenAI but intend to within the next two years) |\n",
"| In development | 61% | 64% | 69% | 52% |\n",
"| Ad hoc or informal | 21% | 3% | 13% | 34% |\n",
"| Nonexistent | 6% | 0% | 0% | 13% |\n",
"| GenAI Governance framework | | | | |\n",
"| Well-established and comprehensive | 5% | 29% | 4% | 0% |\n",
"| In development | 55% | 58% | 78% | 31% |\n",
"| Ad hoc or informal | 28% | 13% | 17% | 43% |\n",
"| Nonexistent | 11% | 0% | 0% | 26% |\n",
"\n",
"## How would you describe your current GenAI/AI governance framework?\n",
"\n",
"### Artificial Intelligence (AI) Governance framework\n",
"\n",
"<table>\n",
" <thead>\n",
" <tr>\n",
" <th></th>\n",
" <th>Well-established and comprehensive</th>\n",
" <th>In development</th>\n",
" <th>Ad hoc or informal</th>\n",
" <th>Nonexistent</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <td>All respondents using/planning to use GenAI</td>\n",
" <td>13%</td>\n",
" <td>61%</td>\n",
" <td>21%</td>\n",
" <td>6%</td>\n",
" </tr>\n",
"<tr>\n",
" <td>Using GenAI and have fully implemented it</td>\n",
" <td>33%</td>\n",
" <td>64%</td>\n",
" <td>3%</td>\n",
" <td>0%</td>\n",
" </tr>\n",
"<tr>\n",
" <td>Using GenAI but haven't yet fully implemented it</td>\n",
" <td>18%</td>\n",
" <td>69%</td>\n",
" <td>13%</td>\n",
" <td>0%</td>\n",
" </tr>\n",
"<tr>\n",
" <td>Not yet using GenAI but intend to within the next two years</td>\n",
" <td>1%</td>\n",
" <td>52%</td>\n",
" <td>34%</td>\n",
" <td>13%</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"\n",
"### GenAI Governance framework\n",
"\n",
"<table>\n",
" <thead>\n",
" <tr>\n",
" <th></th>\n",
" <th>Well-established and comprehensive</th>\n",
" <th>In development</th>\n",
" <th>Ad hoc or informal</th>\n",
" <th>Nonexistent</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <td>All respondents using/planning to use GenAI</td>\n",
" <td>5%</td>\n",
" <td>55%</td>\n",
" <td>28%</td>\n",
" <td>11%</td>\n",
" </tr>\n",
"<tr>\n",
" <td>Using GenAI and have fully implemented it</td>\n",
" <td>29%</td>\n",
" <td>58%</td>\n",
" <td>13%</td>\n",
" <td>0%</td>\n",
" </tr>\n",
"<tr>\n",
" <td>Using GenAI but haven't yet fully implemented it</td>\n",
" <td>4%</td>\n",
" <td>78%</td>\n",
" <td>17%</td>\n",
" <td>0%</td>\n",
" </tr>\n",
"<tr>\n",
" <td>Not yet using GenAI but intend to within the next two years</td>\n",
" <td>0%</td>\n",
" <td>31%</td>\n",
" <td>43%</td>\n",
" <td>26%</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"\n",
"<ul>\n",
"<li>All respondents using/planning to use GenAI</li>\n",
"<li>Using GenAI and have fully implemented it</li>\n",
"<li>Using GenAI but haven't yet fully implemented it</li>\n",
"<li>Not yet using GenAI but intend to within the next two years</li>\n",
"</ul>\n",
"\n"
]
}
@@ -470,8 +405,8 @@
"output_type": "stream",
"text": [
"Parsing Apple 10-K with Agentic Plus Mode...\n",
"Started parsing the file under job_id 172dd00c-c2c7-4d48-8867-ab466ecd5539\n",
"Number of pages extracted: 82\n",
"Started parsing the file under job_id bfe790f5-a3c1-455d-8143-9403728772f4\n",
"..Number of pages extracted: 82\n",
"\n",
"=== Sample Output - Page 32 (Agentic Plus Mode) ===\n",
"\n",
@@ -480,196 +415,38 @@
"## CONSOLIDATED STATEMENTS OF OPERATIONS\n",
"*(In millions, except number of shares which are reflected in thousands and per share amounts)*\n",
"\n",
"<table>\n",
"<thead>\n",
"<tr>\n",
"<th></th>\n",
"<th colspan=\"3\">Years ended</th>\n",
"</tr>\n",
"<tr>\n",
"<th></th>\n",
"<th>September 25, 2021</th>\n",
"<th>September 26, 2020</th>\n",
"<th>September 28, 2019</th>\n",
"</tr>\n",
"</thead>\n",
"<tbody>\n",
"<tr>\n",
"<td><strong>Net sales:</strong></td>\n",
"<td></td>\n",
"<td></td>\n",
"<td></td>\n",
"</tr>\n",
"<tr>\n",
"<td> Products</td>\n",
"<td>$ 297,392</td>\n",
"<td>$ 220,747</td>\n",
"<td>$ 213,883</td>\n",
"</tr>\n",
"<tr>\n",
"<td> Services</td>\n",
"<td>68,425</td>\n",
"<td>53,768</td>\n",
"<td>46,291</td>\n",
"</tr>\n",
"<tr>\n",
"<td> Total net sales</td>\n",
"<td>365,817</td>\n",
"<td>274,515</td>\n",
"<td>260,174</td>\n",
"</tr>\n",
"<tr>\n",
"<td></td>\n",
"<td></td>\n",
"<td></td>\n",
"<td></td>\n",
"</tr>\n",
"<tr>\n",
"<td><strong>Cost of sales:</strong></td>\n",
"<td></td>\n",
"<td></td>\n",
"<td></td>\n",
"</tr>\n",
"<tr>\n",
"<td> Products</td>\n",
"<td>192,266</td>\n",
"<td>151,286</td>\n",
"<td>144,996</td>\n",
"</tr>\n",
"<tr>\n",
"<td> Services</td>\n",
"<td>20,715</td>\n",
"<td>18,273</td>\n",
"<td>16,786</td>\n",
"</tr>\n",
"<tr>\n",
"<td> Total cost of sales</td>\n",
"<td>212,981</td>\n",
"<td>169,559</td>\n",
"<td>161,782</td>\n",
"</tr>\n",
"<tr>\n",
"<td> Gross margin</td>\n",
"<td>152,836</td>\n",
"<td>104,956</td>\n",
"<td>98,392</td>\n",
"</tr>\n",
"<tr>\n",
"<td></td>\n",
"<td></td>\n",
"<td></td>\n",
"<td></td>\n",
"</tr>\n",
"<tr>\n",
"<td><strong>Operating expenses:</strong></td>\n",
"<td></td>\n",
"<td></td>\n",
"<td></td>\n",
"</tr>\n",
"<tr>\n",
"<td> Research and development</td>\n",
"<td>21,914</td>\n",
"<td>18,752</td>\n",
"<td>16,217</td>\n",
"</tr>\n",
"<tr>\n",
"<td> Selling, general and administrative</td>\n",
"<td>21,973</td>\n",
"<td>19,916</td>\n",
"<td>18,245</td>\n",
"</tr>\n",
"<tr>\n",
"<td> Total operating expenses</td>\n",
"<td>43,887</td>\n",
"<td>38,668</td>\n",
"<td>34,462</td>\n",
"</tr>\n",
"<tr>\n",
"<td></td>\n",
"<td></td>\n",
"<td></td>\n",
"<td></td>\n",
"</tr>\n",
"<tr>\n",
"<td><strong>Operating income</strong></td>\n",
"<td>108,949</td>\n",
"<td>66,288</td>\n",
"<td>63,930</td>\n",
"</tr>\n",
"<tr>\n",
"<td><strong>Other income/(expense), net</strong></td>\n",
"<td>258</td>\n",
"<td>803</td>\n",
"<td>1,807</td>\n",
"</tr>\n",
"<tr>\n",
"<td><strong>Income before provision for income taxes</strong></td>\n",
"<td>109,207</td>\n",
"<td>67,091</td>\n",
"<td>65,737</td>\n",
"</tr>\n",
"<tr>\n",
"<td><strong>Provision for income taxes</strong></td>\n",
"<td>14,527</td>\n",
"<td>9,680</td>\n",
"<td>10,481</td>\n",
"</tr>\n",
"<tr>\n",
"<td><strong>Net income</strong></td>\n",
"<td>$ 94,680</td>\n",
"<td>$ 57,411</td>\n",
"<td>$ 55,256</td>\n",
"</tr>\n",
"<tr>\n",
"<td></td>\n",
"<td></td>\n",
"<td></td>\n",
"<td></td>\n",
"</tr>\n",
"<tr>\n",
"<td><strong>Earnings per share:</strong></td>\n",
"<td></td>\n",
"<td></td>\n",
"<td></td>\n",
"</tr>\n",
"<tr>\n",
"<td> Basic</td>\n",
"<td>$ 5.67</td>\n",
"<td>$ 3.31</td>\n",
"<td>$ 2.99</td>\n",
"</tr>\n",
"<tr>\n",
"<td> Diluted</td>\n",
"<td>$ 5.61</td>\n",
"<td>$ 3.28</td>\n",
"<td>$ 2.97</td>\n",
"</tr>\n",
"<tr>\n",
"<td></td>\n",
"<td></td>\n",
"<td></td>\n",
"<td></td>\n",
"</tr>\n",
"<tr>\n",
"<td><strong>Shares used in computing earnings per share:</strong></td>\n",
"<td></td>\n",
"<td></td>\n",
"<td></td>\n",
"</tr>\n",
"<tr>\n",
"<td> Basic</td>\n",
"<td>16,701,272</td>\n",
"<td>17,352,119</td>\n",
"<td>18,471,336</td>\n",
"</tr>\n",
"<tr>\n",
"<td> Diluted</td>\n",
"<td>16,864,919</td>\n",
"<td>17,528,214</td>\n",
"<td>18,595,651</td>\n",
"</tr>\n",
"</tbody>\n",
"</table>\n",
"| | Years ended<br/>September 25, 2021 | Years ended<br/>September 26, 2020 | Years ended<br/>September 28, 2019 |\n",
"| ------------------------------------------------ | ---------------------------------- | ---------------------------------- | ---------------------------------- |\n",
"| **Net sales:** | | | |\n",
"| Products | $ 297,392 | $ 220,747 | $ 213,883 |\n",
"| Services | 68,425 | 53,768 | 46,291 |\n",
"| Total net sales | 365,817 | 274,515 | 260,174 |\n",
"| | | | |\n",
"| **Cost of sales:** | | | |\n",
"| Products | 192,266 | 151,286 | 144,996 |\n",
"| Services | 20,715 | 18,273 | 16,786 |\n",
"| Total cost of sales | 212,981 | 169,559 | 161,782 |\n",
"| Gross margin | 152,836 | 104,956 | 98,392 |\n",
"| | | | |\n",
"| **Operating expenses:** | | | |\n",
"| Research and development | 21,914 | 18,752 | 16,217 |\n",
"| Selling, general and administrative | 21,973 | 19,916 | 18,245 |\n",
"| Total operating expenses | 43,887 | 38,668 | 34,462 |\n",
"| | | | |\n",
"| **Operating income** | 108,949 | 66,288 | 63,930 |\n",
"| **Other income/(expense), net** | 258 | 803 | 1,807 |\n",
"| **Income before provision for income taxes** | 109,207 | 67,091 | 65,737 |\n",
"| **Provision for income taxes** | 14,527 | 9,680 | 10,481 |\n",
"| **Net income** | $ 94,680 | $ 57,411 | $ 55,256 |\n",
"| | | | |\n",
"| **Earnings per share:** | | | |\n",
"| Basic | $ 5.67 | $ 3.31 | $ 2.99 |\n",
"| Diluted | $ 5.61 | $ 3.28 | $ 2.97 |\n",
"| | | | |\n",
"| **Shares used in computing earnings per share:** | | | |\n",
"| Basic | 16,701,272 | 17,352,119 | 18,471,336 |\n",
"| Diluted | 16,864,919 | 17,528,214 | 18,595,651 |\n",
"\n",
"\n",
"See accompanying Notes to Consolidated Financial Statements.\n",
"\n",
@@ -758,12 +535,11 @@
"output_type": "stream",
"text": [
"=== Apple 10-K Financial Data Answer ===\n",
"The 10K table shows (in millions) for the year ended September 25, 2021:\n",
"- Products: $297,392 million\n",
"- Services: $68,425 million\n",
"- Total net sales: $365,817 million\n",
"For the period shown (year ended September 25, 2021) net sales were (in millions):\n",
"\n",
"Note: the table is the consolidated statement of operations for the fiscal year ended Sept. 25, 2021. If you meant fiscal Q3 (a single quarter), let me know and I can pull the quarterly figures.\n"
"- Products: $297,392\n",
"- Services: $68,425\n",
"- Total net sales: $365,817\n"
]
}
],
@@ -803,25 +579,45 @@
"output_type": "stream",
"text": [
"=== GenAI Regulatory Compliance Answer ===\n",
"Short answer: Very poorly. Only 1 in 10 organizations say they are fully prepared to comply with current/upcoming GenAI regulations.\n",
"Short answer: organizations are largely unprepared — only 1 in 10 fully prepared overall.\n",
"\n",
"Key numbers (all respondents using/planning to use GenAI)\n",
"- Fully prepared: 10% \n",
"- Moderately prepared: 48% \n",
"- Slightly prepared: 40% \n",
"- Not prepared: 2%\n",
"Details (from the report)\n",
"\n",
"Breakdown by adoption stage\n",
"- Using GenAI and fully implemented: 35% fully prepared, 49% moderately, 15% slightly, 0% not prepared. \n",
"- Using GenAI but not fully implemented: 11% fully prepared, 66% moderately, 23% slightly, 0% not prepared. \n",
"- Not yet using but intend to within 2 years: 3% fully prepared, 28% moderately, 64% slightly, 5% not prepared.\n",
"Compliance preparedness (current & upcoming GenAI regulations)\n",
"- All respondents using / planning to use GenAI\n",
" - Fully prepared: 10%\n",
" - Moderately prepared: 48%\n",
" - Slightly prepared: 40%\n",
" - Not prepared: 2%\n",
"- Using GenAI and have fully implemented it\n",
" - Fully prepared: 35%\n",
" - Moderately prepared: 49%\n",
" - Slightly prepared: 15%\n",
" - Not prepared: 0%\n",
"- Using GenAI but not yet fully implemented\n",
" - Fully prepared: 11%\n",
" - Moderately prepared: 66%\n",
" - Slightly prepared: 23%\n",
" - Not prepared: 0%\n",
"- Not yet using GenAI but intend to within two years\n",
" - Fully prepared: 3%\n",
" - Moderately prepared: 28%\n",
" - Slightly prepared: 64%\n",
" - Not prepared: 5%\n",
"\n",
"Related governance context\n",
"- AI governance (all respondents): 13% have a wellestablished/comprehensive framework; 61% in development; 21% ad hoc; 6% nonexistent. \n",
"- GenAI governance (all respondents): only 5% wellestablished; 55% in development; 28% ad hoc; 11% nonexistent. \n",
"- Among organizations that have fully implemented GenAI, only 29% have a wellestablished GenAI governance framework — meaning ~71% of adopters lack a comprehensive GenAI governance framework (the “seven in 10” cited).\n",
"Governance context (AI / GenAI frameworks)\n",
"- GenAI governance (all respondents)\n",
" - Wellestablished & comprehensive: 5%\n",
" - In development: 55%\n",
" - Ad hoc/informal: 28%\n",
" - Nonexistent: 11%\n",
"- GenAI governance (using GenAI and fully implemented)\n",
" - Wellestablished: 29% (so 71% do not have a wellestablished GenAI framework)\n",
" - In development: 58%\n",
" - Ad hoc: 13%\n",
" - Nonexistent: 0%\n",
"\n",
"(Percentages may not sum to exactly 100% due to rounding.)\n"
"Interpretation: only 10% of organizations overall say they are fully prepared to comply; most are moderately (48%) or slightly (40%) prepared. GenAI governance is rarely comprehensive (5% overall), and even among fully implemented users only 29% have a wellestablished GenAI governance framework — meaning roughly 7 in 10 adopters still lack a comprehensive framework.\n"
]
}
],
+27 -28
View File
@@ -17,7 +17,6 @@ from llama_index.core.async_utils import asyncio_run, run_jobs
from llama_index.core.bridge.pydantic import (
Field,
PrivateAttr,
field_validator,
model_validator,
)
from llama_index.core.constants import DEFAULT_BASE_URL
@@ -105,17 +104,29 @@ class BackoffPattern(str, Enum):
EXPONENTIAL = "exponential"
def _get_default_api_key() -> str:
env_key = os.getenv("LLAMA_CLOUD_API_KEY")
if env_key is None:
raise ValueError("The API key is required.")
return env_key
def _get_default_base_url() -> str:
env_url = os.getenv("LLAMA_CLOUD_BASE_URL")
return env_url or DEFAULT_BASE_URL
class LlamaParse(BasePydanticReader):
"""A smart-parser for files."""
# Library / access specific configurations
api_key: str = Field(
default="",
default_factory=_get_default_api_key,
description="The API key for the LlamaParse API.",
validate_default=True,
)
base_url: str = Field(
default=DEFAULT_BASE_URL,
default_factory=_get_default_base_url,
description="The base URL of the Llama Parsing API.",
)
organization_id: Optional[str] = Field(
@@ -561,27 +572,6 @@ class LlamaParse(BasePydanticReader):
return data
@field_validator("api_key", mode="before", check_fields=True)
@classmethod
def validate_api_key(cls, v: str) -> str:
"""Validate the API key."""
if not v:
import os
api_key = os.getenv("LLAMA_CLOUD_API_KEY", None)
if api_key is None:
raise ValueError("The API key is required.")
return api_key
return v
@field_validator("base_url", mode="before", check_fields=True)
@classmethod
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
_aclient: Union[httpx.AsyncClient, None] = PrivateAttr(default=None, init=False)
@property
@@ -1025,11 +1015,20 @@ class LlamaParse(BasePydanticReader):
try:
url = build_url(JOB_UPLOAD_ROUTE, self.organization_id, self.project_id)
resp = await make_api_request(self.aclient, "POST", url, timeout=self.max_timeout, files=files, data=data) # type: ignore
resp.raise_for_status() # this raises if status is not 2xx
# Note: make_api_request already calls raise_for_status(), so no need to call it again
return resp.json()["id"]
except httpx.HTTPStatusError as err: # this catches it
except httpx.HTTPStatusError as err: # this catches HTTP status errors
msg = f"Failed to parse the file: {err.response.text}"
raise Exception(msg) from err # this preserves the exception context
except Exception as err: # this catches other exceptions like RetryError, ValueError, etc.
# Try to extract meaningful error message from the exception chain
if hasattr(err, '__cause__') and isinstance(err.__cause__, httpx.HTTPStatusError):
# If the exception was caused by an HTTPStatusError, extract the response text
msg = f"Failed to parse the file: {err.__cause__.response.text}"
else:
# For other exceptions, use the string representation
msg = f"Failed to parse the file: {str(err)}"
raise Exception(msg) from err
finally:
if file_handle is not None:
file_handle.close()
@@ -1588,7 +1587,7 @@ class LlamaParse(BasePydanticReader):
resp = await make_api_request(
client, "GET", asset_url, timeout=self.max_timeout
)
resp.raise_for_status()
# Note: make_api_request already calls raise_for_status()
f.write(resp.content)
assets.append(asset)
return assets
@@ -1686,7 +1685,7 @@ class LlamaParse(BasePydanticReader):
res = await make_api_request(
client, "GET", xlsx_url, timeout=self.max_timeout
)
res.raise_for_status()
# Note: make_api_request already calls raise_for_status()
f.write(res.content)
xlsx_list.append(xlsx)
return xlsx_list
+12 -1
View File
@@ -11,6 +11,7 @@ from tenacity import (
wait_exponential,
retry_if_exception,
before_sleep_log,
RetryError,
)
from typing import Any, Iterable, Iterator, Optional, List, cast
@@ -300,7 +301,17 @@ async def make_api_request(
response.raise_for_status()
return response
return await _make_request(url, **httpx_kwargs)
try:
return await _make_request(url, **httpx_kwargs)
except RetryError as retry_err:
# Extract the last exception from the retry error to preserve the original error details
if retry_err.last_attempt and retry_err.last_attempt.exception():
last_exception = retry_err.last_attempt.exception()
# Re-raise the original exception to preserve error details like response.text
raise last_exception from retry_err
else:
# Fallback if we can't extract the original exception
raise retry_err
def expand_target_pages(target_pages: str) -> Iterator[int]:
+2 -2
View File
@@ -11,13 +11,13 @@ dev = [
[project]
name = "llama-parse"
version = "0.6.60"
version = "0.6.62"
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.60"]
dependencies = ["llama-cloud-services>=0.6.62"]
[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.61"
version = "0.6.62"
description = "Tailored SDK clients for LlamaCloud services."
authors = [{name = "Logan Markewich", email = "logan@runllama.ai"}]
requires-python = ">=3.9,<4.0"
+57
View File
@@ -0,0 +1,57 @@
from collections.abc import Generator
import pytest
import os
from llama_cloud_services.parse.base import LlamaParse
@pytest.fixture(autouse=True)
def clear_env() -> Generator[None, None, None]:
"""entirely clear the environment, and then reset after test completion"""
original_env = os.environ.copy()
os.environ.clear()
try:
yield
finally:
os.environ.clear()
os.environ.update(original_env)
def test_should_obtain_api_key_base_url_from_env_vars():
os.environ["LLAMA_CLOUD_API_KEY"] = "test-api-key"
os.environ["LLAMA_CLOUD_BASE_URL"] = "https://example.test"
client = LlamaParse()
assert client.api_key == "test-api-key"
assert client.base_url == "https://example.test"
def test_should_be_able_to_pass_api_key_base_url_as_kwargs():
os.environ["LLAMA_CLOUD_API_KEY"] = "not-this-one"
os.environ["LLAMA_CLOUD_BASE_URL"] = "https://wrong.site"
client = LlamaParse(
api_key="test-api-key",
base_url="https://example.test",
)
assert client.api_key == "test-api-key"
assert client.base_url == "https://example.test"
def test_should_raise_error_if_api_key_is_not_provided():
with pytest.raises(ValueError, match="The API key is required."):
LlamaParse()
def test_should_default_to_llama_cloud_base_url_if_not_provided():
client = LlamaParse(
api_key="test-api-key",
)
assert client.base_url == "https://api.cloud.llamaindex.ai"
def test_json_parseable():
os.environ["LLAMA_CLOUD_API_KEY"] = "test-api-key"
client2 = LlamaParse.model_validate_json('{"base_url":"https://example.test"}')
assert client2.api_key == "test-api-key"
assert client2.base_url == "https://example.test"