循序渐进 · AIP 教学 · 文档智能(四)
把抽取策略部署到 Python 函数
如果需要按需、单次抽取(而不是批量跑),部署成函数更合适。这篇给出操作路径与生成的代码。
本文来源 · Source
内容整理自 Palantir Foundry 官方文档:
https://www.palantir.com/docs/foundry/document-intelligence/deploy-to-python-functions/
原始标题:AIP Document Intelligence • Deploy extraction strategies to Python functions • Palantir · 所属:AIP Document Intelligence(读懂文档)
https://www.palantir.com/docs/foundry/document-intelligence/deploy-to-python-functions/
原始标题:AIP Document Intelligence • Deploy extraction strategies to Python functions • Palantir · 所属:AIP Document Intelligence(读懂文档)
★
先记住这几条
① 适用按需场景
一次处理一份文档,而非批量。
② 用生成的代码起步
官方给出可参考的代码片段。
③ 与 transform 是互补关系
按业务形态选。
0
写在前面
按照 AIP Document Intelligence 中的 Deploy to functions 指南进行操作,并使用生成的代码片段,用你的抽取策略搭建一个 Python functions 仓库。
1
配置
要点:代码与参数设置。
要在 functions 中开始文档抽取,首先创建一个 Python functions 仓库,或使用已有的仓库。
使用正确的导入和权限来设置仓库,以便运行文档抽取:
- 安装平台 SDK(如果尚未安装):
- 在左侧面板中选择 Libraries 以添加一个库。
- 安装
foundry-platform-sdk版本 >= 1.78。 - 如果你需要分块(chunking),安装
aip-workflows版本 >= 0.40.0。 - 如果你想做嵌入(embedding),安装
openai。
- 对于基于 LLM 的抽取,将你选择的模型导入到仓库中。
- 将该 function 设置为具有更长的超时时间。我们建议选择你的注册所允许的最大值。要处理大量 PDF 以及页数很多的 PDF,你需要将这些 functions 作为抽取策略的一部分来使用。
以下各节解释了 Deploy to functions 指南中包含的各种代码片段。
2
辅助函数
要点:官方提供的工具函数。
辅助函数对所有抽取策略都相同。你可以将它们复制到与你的 function 相同的 Python 文件中,如果你有多个 function,也可以复制到一个共享的工具文件中。它们在平台内可用,下面也一并列出以供参考。
from dataclasses import dataclass
from time import sleep
from typing import Optional
from foundry_sdk import FoundryClient
from foundry_sdk._errors import PalantirException, PalantirQoSException, PalantirRPCException
from foundry_sdk._errors.palantir_qos_exception import QoSRetryHint
from foundry_sdk.v2.media_sets import models
from functions.api import function
@dataclass
class TransformResult:
"""The outcome of a transform. Functions return this instead of raising on failure so your
orchestration can branch on the result.
result: The extracted content (Markdown or JSON, depending on your configuration) on success,
otherwise None.
error: The specific error name on failure (or a human-readable reason for rate-limit and
availability errors), otherwise None.
retryable: True when the failure is transient (rate limits or service availability) and worth
retrying, False when it is not, and None on success.
"""
result: Optional[str]
error: Optional[str]
retryable: Optional[bool]
def _create_transform_job(
media_set_rid: str, media_item_rid: str, transformation: models.DocumentToTextTransformation
) -> str:
fc = FoundryClient()
job_initiation_resp = fc.media_sets.MediaSet.transform(
media_set_rid=media_set_rid,
media_item_rid=media_item_rid,
transformation=transformation,
preview=True,
)
job_id = job_initiation_resp.job_id
return job_id
def _is_transform_finished(media_set_rid: str, media_item_rid: str, job_id: str) -> bool:
fc = FoundryClient()
status = fc.media_sets.MediaSet.get_status(media_set_rid, media_item_rid, job_id, preview=True)
return status.status in ("SUCCESSFUL", "FAILED")
def _get_transform_result(media_set_rid: str, media_item_rid: str, job_id: str) -> str:
fc = FoundryClient()
result = fc.media_sets.MediaSet.get_result(media_set_rid, media_item_rid, job_id, preview=True)
return result.decode("utf-8")
def _run_transform_blocking(
media_set_rid: str, media_item_rid: str, transformation: models.DocumentToTextTransformation
) -> str:
job_id = _create_transform_job(media_set_rid, media_item_rid, transformation)
while not _is_transform_finished(media_set_rid, media_item_rid, job_id):
sleep(0.5)
return _get_transform_result(media_set_rid, media_item_rid, job_id)
def _run_transform_error_handled(
media_set_rid: str, media_item_rid: str, transformation: models.DocumentToTextTransformation
) -> TransformResult:
try:
result_text = _run_transform_blocking(media_set_rid, media_item_rid, transformation)
return TransformResult(result=result_text, error=None, retryable=None)
except PalantirQoSException as e:
retryable = e.retry_hint != QoSRetryHint.DO_NOT_RETRY
return TransformResult(result=None, error=e.reason, retryable=retryable)
except PalantirRPCException as e:
return TransformResult(result=None, error=e.name or type(e).__name__, retryable=False)
except PalantirException as e:
return TransformResult(result=None, error=type(e).__name__, retryable=False)3
你的抽取策略
要点:核心逻辑怎么写。
此 function 对应你的抽取策略,需要一个媒体输入以及给定的页面。由于该 function 是动态生成的,请从应用内复制代码。你以任何名称发布它都会按该名称注册,因此你可以按需重命名。你可以将媒体输入以「媒体集 RID + 媒体项 RID 字符串」组合的形式提供,也可以作为对象属性提供;使用左上角的选择器来选择模板。对象属性模板要求你导入你的对象。

4
分块与嵌入函数
要点:为下游检索做准备的环节。
你可以选择性地对抽取出的文本进行分块并生成嵌入,以供搜索或检索工作流的下游使用。下面的 functions 是静态的;分块大小、分块重叠量和嵌入模型在应用中配置,因此请将默认参数值替换为你所选的值。
from functions.api import function, Array, Boolean, Float, Integer, String
from aip_workflows.document_intelligence.transforms import DocumentChunker
@function(beta=True)
def chunk_text(
texts: Array[String],
chunk_size: Integer = 8192,
chunk_overlap: Integer = 0,
concat_before_chunk: Boolean = False,
chunk_mode: String = "markdown",
) -> Array[Array[String]]:
"""
Chunks a list of text strings.
Args:
texts: A list of text strings to chunk.
chunk_size: Maximum number of characters per chunk.
chunk_overlap: Number of overlapping characters between consecutive chunks.
concat_before_chunk: If True, concatenates all texts into a single string before chunking,
returning a single inner list. Recommended when input is per-page text of a document.
If False, chunks each text independently, returning one inner list per input text.
chunk_mode: The chunking strategy to use. Options:
- "markdown": Recommended for Markdown text.
- "recursive": Recommended for raw text without any format.
Returns:
A list of lists of chunk strings. Each inner list contains the chunks for one input text.
When concat_before_chunk is True, input texts are concatenated into a single string so the
output list has length of 1.
"""
chunks = DocumentChunker.create_chunks(
texts,
chunk_mode=chunk_mode,
chunk_size=chunk_size,
chunk_overlap=chunk_overlap,
strip_markdown=True,
concat_before_chunk=concat_before_chunk,
)
if concat_before_chunk:
return [chunks]
return chunks
from foundry_sdk.v2.language_models.utils import (
get_foundry_token,
get_openai_base_url,
get_http_client,
)
from openai import OpenAI
@function(beta=True)
def embed_text(
texts: Array[String],
embedding_model_rid: String = "<YOUR_EMBEDDING_MODEL_RID>",
) -> Array[Array[Float]]:
"""
Generates embeddings for a list of text strings using the configured embedding model.
Args:
texts: A list of text strings to embed.
embedding_model_rid: The RID of the embedding model to use.
Returns:
A list of vector embeddings, one per input text.
"""
client = OpenAI(
api_key=get_foundry_token(preview=True),
base_url=get_openai_base_url(preview=True),
http_client=get_http_client(preview=True),
)
response = client.embeddings.create(
input=texts,
model=embedding_model_rid,
)
return [response.data[i].embedding for i in range(len(texts))]延伸阅读 · 相关页面
按主题横向跳转,不必顺着目录一篇篇读。
本组其他页面 · AIP Document Intelligence(读懂文档)
同一主题下的相邻内容。
常见问题速答 · FAQ
关于「把抽取策略部署到 Python 函数」,读者最常问的几个问题。
如何配置?
代码与参数设置。要在 functions 中开始文档抽取,首先创建一个 Python functions 仓库,或使用已有的仓库。
辅助函数是什么?
官方提供的工具函数。辅助函数对所有抽取策略都相同。你可以将它们复制到与你的 function 相同的 Python 文件中,如果你有多个 function,也可以复制到一个共享的工具文件中。它们在平台内可用,下面也一并列出以供参考。
你的抽取策略是什么?
核心逻辑怎么写。此 function 对应你的抽取策略,需要一个媒体输入以及给定的页面。由于该 function 是动态生成的,请从应用内复制代码。你以任何名称发布它都会按该名称注册,因此你可以按需重命名。
分块与嵌入函数是什么?
为下游检索做准备的环节。你可以选择性地对抽取出的文本进行分块并生成嵌入,以供搜索或检索工作流的下游使用。下面的 functions 是静态的;分块大小、分块重叠量和嵌入模型在应用中配置,因此请将默认参数值替换为你所选的值。