> ## Documentation Index
> Fetch the complete documentation index at: https://docs.wengaocloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 文档理解

> 使用 Gemini 原生 fileData.fileUri 或 inlineData 解析 PDF、DOCX、TXT 等文档内容。

Gemini 原生文档理解适合合同摘要、简历解析、报告问答、发票/表格信息提取、知识库文档预审等场景。原生格式可以把文档作为 `parts` 中的文件片段传入，并用文本指令明确需要总结、抽取、分类还是问答。

<Note>
  联调、小文件和客户本地文件推荐优先使用 `inlineData`，这是最不依赖外部下载环境的方式。公网 URL 也可以使用 `fileData.fileUri`，但必须确保它是上游可直接读取、返回真实文件 MIME 类型的直链；HTTP 请求被接受不等于模型已经读到正文。
</Note>

## 接口地址

非流式：

```http theme={null}
POST https://{your-domain}/v1beta/models/{model}:generateContent
```

流式：

```http theme={null}
POST https://{your-domain}/v1beta/models/{model}:streamGenerateContent?alt=sse
```

示例模型：

```text theme={null}
gemini-3.5-flash
```

## 鉴权

推荐：

```http theme={null}
x-goog-api-key: YOUR_API_KEY
Content-Type: application/json
```

兼容：

```http theme={null}
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
```

## 支持的输入方式

| 方式          | 适用场景                                        | 请求字段                                      |
| ----------- | ------------------------------------------- | ----------------------------------------- |
| Base64 内联文件 | 小文件、测试样例、客户本地文件、无法提供公网 URL                  | `inlineData.mimeType` + `inlineData.data` |
| 公网文件 URL    | 文件已在对象存储、CDN 或公开下载地址中，且能返回正确 `Content-Type` | `fileData.mimeType` + `fileData.fileUri`  |
| 文本粘贴        | TXT、Markdown、已提取纯文本                         | 直接放入 `parts[].text`                       |

常见 MIME 类型：

| 文件类型         | MIME 类型                                                                   |
| ------------ | ------------------------------------------------------------------------- |
| PDF          | `application/pdf`                                                         |
| TXT          | `text/plain`                                                              |
| Markdown     | `text/markdown`                                                           |
| DOCX         | `application/vnd.openxmlformats-officedocument.wordprocessingml.document` |
| PNG/JPEG 扫描件 | `image/png`、`image/jpeg`                                                  |

<Warning>
  `fileUri` 必须是上游模型可匿名访问的文件直链，并且下载响应的 `Content-Type` 要与 `mimeType` 一致。不要传本地路径、内网地址、需要登录 Cookie 的下载页、短时间过期链接、HTML 预览页或会跳转到网页的地址。若客户无法确认 URL 一定可被上游读取，请使用 `inlineData`。
</Warning>

## 使用 Base64 内联文件

小文件可以直接用 `inlineData` 传入。`data` 字段只放 Base64 内容，不要包含 `data:application/pdf;base64,` 前缀。

### curl

```bash theme={null}
curl --request POST \
  --url 'https://{your-domain}/v1beta/models/gemini-3.5-flash:generateContent' \
  --header 'x-goog-api-key: YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "contents": [
      {
        "role": "user",
        "parts": [
          {
            "text": "请阅读这份 PDF，用中文输出：1. 核心摘要；2. 三条要点；3. 可能需要人工复核的字段。"
          },
          {
            "inlineData": {
              "mimeType": "application/pdf",
              "data": "JVBERi0xLjcKJcTl8uXrp..."
            }
          }
        ]
      }
    ],
    "generationConfig": {
      "maxOutputTokens": 1024,
      "temperature": 0.2
    }
  }'
```

### 请求体

```json theme={null}
{
  "contents": [
    {
      "role": "user",
      "parts": [
        {
          "text": "请阅读这份 PDF，用中文输出：1. 核心摘要；2. 三条要点；3. 可能需要人工复核的字段。"
        },
        {
          "inlineData": {
            "mimeType": "application/pdf",
            "data": "JVBERi0xLjcKJcTl8uXrp..."
          }
        }
      ]
    }
  ],
  "generationConfig": {
    "maxOutputTokens": 1024,
    "temperature": 0.2
  }
}
```

### 响应示例

```json theme={null}
{
  "candidates": [
    {
      "content": {
        "role": "model",
        "parts": [
          {
            "text": "1. 核心摘要：这份 PDF 内容较短，主要用于验证文件读取和文档解析流程。\n\n2. 三条要点：\n- 文档结构简单，正文较少。\n- 可作为接口联调样例。\n- 不包含复杂表格、签章或多页长文本。\n\n3. 需要人工复核的字段：如果换成真实业务文件，合同金额、日期、签署方、身份证号、发票号码等字段建议人工复核。"
          }
        ]
      },
      "finishReason": "STOP",
      "index": 0,
      "safetyRatings": []
    }
  ],
  "usageMetadata": {
    "promptTokenCount": 612,
    "candidatesTokenCount": 145,
    "totalTokenCount": 757
  }
}
```

## 使用公网 PDF URL

如果文件已经在客户对象存储或 CDN 中，并且可以被上游模型匿名下载，可以使用 `fileData.fileUri`。请先用一个“是否读到正文”的探针请求验证 URL 真的被模型读取，而不是只被网关接受。

```json theme={null}
{
  "contents": [
    {
      "role": "user",
      "parts": [
        {
          "text": "请阅读这个公网 PDF。如果你确实读取到了 PDF 正文，第一行输出 DOC_URL_SEEN=YES；否则输出 DOC_URL_SEEN=NO。然后用一句话说明文档内容。"
        },
        {
          "fileData": {
            "mimeType": "application/pdf",
            "fileUri": "https://example.com/sample.pdf"
          }
        }
      ]
    }
  ],
  "generationConfig": {
    "maxOutputTokens": 512,
    "temperature": 0.1
  }
}
```

<Warning>
  如果响应内容为 `DOC_URL_SEEN=NO`、模型只复述 URL、或者错误提示上游下载到 `text/html`，说明这个 URL 不是可用的文档直链。请改用 `inlineData`，或把文件转存到返回正确 `application/pdf` 的稳定直链。
</Warning>

## 流式文档理解

文档较大时，流式输出可以更早让客户看到摘要片段。

```bash theme={null}
curl -N --request POST \
  --url 'https://{your-domain}/v1beta/models/gemini-3.5-flash:streamGenerateContent?alt=sse' \
  --header 'x-goog-api-key: YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "contents": [
      {
        "role": "user",
        "parts": [
          {
            "text": "请流式总结这份 PDF，先输出摘要，再输出要点列表。"
          },
          {
            "inlineData": {
              "mimeType": "application/pdf",
              "data": "JVBERi0xLjcKJcTl8uXrp..."
            }
          }
        ]
      }
    ],
    "generationConfig": {
      "maxOutputTokens": 1024
    }
  }'
```

响应为 SSE：

```text theme={null}
data: {"candidates":[{"content":{"role":"model","parts":[{"text":"摘要："}]},"finishReason":null,"index":0}],"usageMetadata":{"promptTokenCount":600,"totalTokenCount":600}}

data: {"candidates":[{"content":{"role":"model","parts":[{"text":"这份 PDF 是一个简短的测试文档，主要用于验证 PDF 文件读取能力。"}]},"finishReason":null,"index":0}],"usageMetadata":{"promptTokenCount":600,"totalTokenCount":600}}

data: {"candidates":[{"content":{"role":"model","parts":[{"text":"\n要点：\n- 文档内容较少。\n- 适合作为接口联调样例。\n- 真实业务需替换为业务文件。"}]},"finishReason":"STOP","index":0}],"usageMetadata":{"promptTokenCount":600,"candidatesTokenCount":72,"totalTokenCount":672}}
```

## 结构化抽取示例

配合 `responseMimeType: "application/json"`，可以让模型按固定字段返回。

```json theme={null}
{
  "systemInstruction": {
    "parts": [
      {
        "text": "你是文档信息抽取助手。只返回 JSON，不要返回 Markdown。字段缺失时使用 null。"
      }
    ]
  },
  "contents": [
    {
      "role": "user",
      "parts": [
        {
          "text": "从文档中提取 title、date、parties、amount、summary。"
        },
        {
          "inlineData": {
            "mimeType": "application/pdf",
            "data": "JVBERi0xLjcKJcTl8uXrp..."
          }
        }
      ]
    }
  ],
  "generationConfig": {
    "responseMimeType": "application/json",
    "maxOutputTokens": 1200,
    "temperature": 0.1
  }
}
```

## Python 示例

```python theme={null}
import requests
import base64
from pathlib import Path

api_key = "YOUR_API_KEY"
model = "gemini-3.5-flash"
url = f"https://{{your-domain}}/v1beta/models/{model}:generateContent"
pdf_base64 = base64.b64encode(Path("sample.pdf").read_bytes()).decode("utf-8")

payload = {
    "contents": [
        {
            "role": "user",
            "parts": [
                {"text": "请总结这份 PDF，并列出三条要点。"},
                {
                    "inlineData": {
                        "mimeType": "application/pdf",
                        "data": pdf_base64,
                    }
                },
            ],
        }
    ],
    "generationConfig": {"maxOutputTokens": 1024},
}

resp = requests.post(
    url,
    headers={
        "x-goog-api-key": api_key,
        "Content-Type": "application/json",
    },
    json=payload,
    timeout=180,
)
resp.raise_for_status()
print(resp.json())
```

## JavaScript 示例

```javascript theme={null}
import fs from "node:fs";

const apiKey = "YOUR_API_KEY";
const model = "gemini-3.5-flash";
const pdfBase64 = fs.readFileSync("sample.pdf").toString("base64");

const response = await fetch(
  `https://{your-domain}/v1beta/models/${model}:generateContent`,
  {
    method: "POST",
    headers: {
      "x-goog-api-key": apiKey,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      contents: [
        {
          role: "user",
          parts: [
            { text: "请总结这份 PDF，并列出三条要点。" },
            {
              inlineData: {
                mimeType: "application/pdf",
                data: pdfBase64,
              },
            },
          ],
        },
      ],
      generationConfig: {
        maxOutputTokens: 1024,
      },
    }),
  }
);

if (!response.ok) {
  throw new Error(await response.text());
}

console.log(await response.json());
```

## 最佳实践

| 建议                 | 说明                                                                |
| ------------------ | ----------------------------------------------------------------- |
| 先说明输出格式            | 例如「摘要 + 要点 + 风险」或「只返回 JSON」。                                      |
| 对抽取任务降低温度          | 建议 `temperature` 为 `0.1` 到 `0.3`。                                 |
| 联调优先用 `inlineData` | 不依赖外部 URL、重定向、对象存储权限和响应头，最容易确认模型确实读到文件。                           |
| 大文件再考虑 URL         | Base64 会增大请求体；使用 URL 时必须确认是直链，且响应 `Content-Type` 与 `mimeType` 一致。 |
| 扫描件可当图片处理          | 如果 PDF 是纯扫描件，可先测试直接 PDF；识别不佳时转图片或提供页面截图。                          |
| 保留人工复核             | 合同金额、日期、签署方、票据号码等关键字段建议人工复核。                                      |

## 常见问题

| 场景                 | 表现                              | 处理方式                                                   |
| ------------------ | ------------------------------- | ------------------------------------------------------ |
| 返回无法读取文档           | 文件 URL 不可访问、MIME 不正确或文件过期       | 检查 URL、MIME 类型和签名有效期。                                  |
| 公网 PDF URL 被当成网页   | 错误里出现 `text/html`，或模型返回没有读到正文   | 改成真正的 PDF 直链，或使用 `inlineData`。                         |
| 请求 HTTP 200 但未读到正文 | 模型返回 `DOC_URL_SEEN=NO` 或只复述 URL | 这不算文档理解成功；请换成 `inlineData` 或稳定文件直链。                    |
| 抽取字段为空             | 文档是扫描件、清晰度低或字段名称不明显             | 提高文件清晰度，在 prompt 中列出字段别名。                              |
| JSON 格式不合法         | 模型返回说明文字或 Markdown              | 使用 `responseMimeType: "application/json"`，并明确只返回 JSON。 |
| 响应超时               | 文件过大或上游读取慢                      | 缩小文档、拆页、改用流式或增加客户端超时时间。                                |
