Perplexity API 教程:逐步构建源接地答案

一个 Python 请求将一个答案引用与源 ID 7 以及 Python 文档关联起来。.

PERPLEXITY API · Python 教程 · 2026

本 Perplexity API 教程将向您展示如何编写一个 Python 脚本,该脚本可返回包含可点击网页来源的答案。使用 Agent API 发送问题、读取答案、将答案中的引用标记与来源 ID 进行匹配,并导出一个可供您查阅的 Markdown 文件。.

我们将始终围绕一个问题展开讨论: 一个小型 Python 项目应该如何使用虚拟环境并管理依赖项? 从一个基本请求开始,然后添加源数据解析和域名过滤功能。您需要具备基本的 Python 知识,并拥有一个已设置 API 计费功能的 Perplexity 开发者账户。.

如果你也在日常的研究和写作中使用人工智能,, Perplexity 位于 GlobalGPT 上 可在一体化 AI 工作区中直接访问,从而减少了在不同工具之间切换的必要。该用户工作流与本文中使用的开发者密钥和 API 计费系统是分开的。.

快速回答: 使用 快 用于首个基于网络的答案的代理预设,请阅读 response.output_text 查看答案,并阅读 搜索结果 项目在 response.output 用于引用来源。根据返回值,将每个内联标记与相应的来源进行匹配 id. 引用意味着“该答案指向了这一结果”;但这并不保证该页面能证明每一项论点。.

状态示例: 该请求语法遵循截至 2026 年 9 月 28 日查阅的官方文档。引用助手已使用离线样本数据进行了验证;本教程中未执行任何付费 API 请求。图中所示的源记录均为说明性示例。.

Perplexity API 教程:选择合适的 API

这些是开发者接口。聊天产品可能会以不同的方式封装类似的功能;我们对 《Perplexity》的游戏特色 描述了面向用户的体验。.

Perplexity的 官方 API 快速入门 根据需要完成的工作来对开发产品进行分类。选择能够生成应用程序实际所需数据的最小工作区。.

应用程序接口最合适您的代码接收到的内容
代理基于网络搜索或其他工具得出的完整答案键入的输出项、答案文本和搜索结果记录
搜索您的应用程序将自动对结果进行排序、筛选或汇总无需让Perplexity写出最终答案的搜索结果
路由器将请求路由到合适的模型通过路由器选定的示例响应
嵌入语义检索与 RAG 索引用于自定义搜索图层的矢量图

本教程选择“Agent”,是因为您想要的结果是一个完整的答案及其来源。关于更广泛的研究工作流程,请参阅我们的指南: 将Perplexity用于研究.

关于 Sonar: 当前的 迁移概述 指出 Sonar 代码补全功能仍受支持,并建议所有新项目使用 Agent。因此,本教程将使用 Agent。请不要仅因旧教程中提到的截止日期,就推断旧的集成功能已停止工作。.

步骤 1:获取 API 密钥并配置 Python

创建密钥并准备计费

打开 Perplexity API 控制台, 选择或创建您要使用的项目,配置 API 计费,并创建一个密钥。请将该密钥保存在服务器端。开发者 API 的计费与用户订阅分开结算;在发送请求前,请先查看您的项目余额。.

安装官方 SDK

python -m venv .venv

# macOS/Linux:请选择此激活命令
source .venv/bin/activate

# Windows PowerShell:请改用此命令
.venv\Scripts\Activate.ps1

python -m pip install --upgrade perplexityai

请使用 Python 3.10 或更高版本运行以下代码。请使用适用于您操作系统的命令激活环境,然后安装 SDK。如果 PowerShell 阻止了环境的激活,请使用 .venv\Scripts\python.exe 代替 蟒蛇 用于安装和脚本执行。.

包名是 perplexityai, ,而 Python 的导入语句是 迷茫. 请使用虚拟环境,以免本教程的依赖项影响其他项目。.

该示例采用了一个编程问题,因为其结论可以通过查阅维护良好的文档来验证。我们的指南 Perplexity 用于编码 解释了研究支持与自己测试代码之间的关系。.

将 API 密钥设置为环境变量

# macOS/Linux
export PERPLEXITY_API_KEY="your-key-here"

# Windows PowerShell
$env:PERPLEXITY_API_KEY = "your-key-here"

SDK 读取 perplexity_api_key 在创建客户端时。请勿将密钥粘贴到记事本中、提交到 Git,或发送至浏览器。如果在本地使用 .env 文件,请将该文件排除在版本控制之外,并通过您选择的环境变量库加载它。.

Perplexity 官方文档,其中介绍了 Python SDK 的安装以及 PERPLEXITY_API_KEY 环境变量。.

步骤 2:发送您的第一个源极接地请求

Agent API 快速入门 文件 POST https://api.perplexity.ai/v1/agent. 其 Python 客户端使用 client.responses.create(). .......。 快 该预设默认启用了网页搜索功能,因此第一个示例的篇幅较短。.

from perplexity import Perplexity

client = Perplexity()

question = (
    "一个小型 Python 项目应该如何使用虚拟环境"
    "并管理依赖项?"
)

response = client.responses.create(
    preset="fast",
    input=question,
)

print(response.output_text)

将代码片段保存为 first_request.py, 然后运行 python first_request.py 在您设置密钥的同一终端中。调用成功时应显示非空的响应文本。如果您需要结果的证明,请继续进行源代码提取步骤;仅凭文本本身并不能算作完整的验证。.

便利性属性 输出文本 会给你最终的答案文本。请同时保留整个响应对象:源记录和使用详情都包含在键入的输出中,而不仅仅是在打印出来的段落里。.

使用 cURL 发送相同的请求

curl https://api.perplexity.ai/v1/agent \
  -H "Authorization: Bearer $PERPLEXITY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "preset": "fast",
    "input": "一个小型 Python 项目应如何使用虚拟环境并管理依赖项?"
  }'

此 cURL 示例采用适用于 macOS/Linux 或与 Bash 兼容的 shell 的 Bash 语法。每次运行都会发起一次计费请求。请仅在需要将端点问题与 Python 问题区分开来时使用此示例;请勿仅为了跟进示例而运行每个版本。.

服务器端 JavaScript 的等效实现

Node.js 18 及以上版本包含 fetch, ,因此服务器端的烟雾测试无需额外库。阅读原始代码 输出 JSON 响应中的项;Python SDK 提供了一个便捷的 输出文本 accessor.

const res = await fetch("https://api.perplexity.ai/v1/agent", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.PERPLEXITY_API_KEY}`,
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    preset: "fast",
    input: "一个小型 Python 项目应该如何使用虚拟环境并管理依赖项?"
  })
});
if (!res.ok) throw new Error(`Perplexity HTTP ${res.status}`);
console.log(await res.json());

第 3 步:提取答案并匹配其来源

官方引用指南 将散文与其证据记录区分开来。资料以一种……的形式出现。 输出 类型为...的项 搜索结果. 阅读该条目的 结果 并将每个引用标记与结果中的 id. 每个结果都有一个标题和一个 URL;在显示结果之前,需先处理缺失的值。.

Perplexity 官方文档,其中解释了编号引用、源类型引用以及将标记与搜索结果 ID 进行匹配的方法。.

最后这一点很重要。不要假设在其他工具添加了一项内容后,“引用 1”总是数组中的第一个元素。应先根据 ID 建立查找机制,然后再确定答案中实际出现的标记。.

def field(obj, name, default=None):
    return obj.get(name, default) if isinstance(obj, dict), else getattr(obj, name, default)

def source_index(output):
    sources = {}
    for item in output or []:
    if field(item, "type") != "search_results":
        continue
    for result in field(item, "results", []) or []:
            sid, url = field(result, "id"), field(result, "url")
 if sid is None:
 continue
 key = str(sid)
 if key in sources and field(sources[key], "url") != url:
                raise ValueError(f"源 ID {key} 的 URL 冲突")
 sources[key] = result
    return sources

sources = source_index(response.output)
print(sources.get("7"))  # 这是一个源 ID,而非数组索引 7

下面的完整脚本可识别 [1] 和 [web:1], ,即常用预设的已记录引用格式。上述辅助函数既支持 SDK 对象,也支持字典,且会拒绝将冲突的 URL 分配给同一个 ID。它不会重新编号结果,也不会对缺失的来源进行推测。.

关于引文质量的更广泛讨论,请参阅我们的 Perplexity 引用准确性指南. 引用是一种审计轨迹;您的应用程序仍需制定针对过期页面、重复 URL 和不受支持的声明的处理策略。.

例如,如果返回的数组中包含 ID 2,后面紧接着是 ID 7,那么该标记 [7] 必须链接到 ID 7。如果同一 URL 同时出现在 ID 7 和 ID 9 下,你可以只显示该 URL 一次,同时保留这两个 ID。如果 ID 8 始终未出现,则保留 [8] 显示出来,并将其标记为“未匹配”。.

即使搜索结果列表中排在第一位的是一条不同的结果,引用 7 仍会与 ID 为 7 的搜索结果相对应。.

第 4 步:使用搜索筛选条件优化答案

一旦基本查询能正常工作,当你的问题有明确的权威范围时,请缩小搜索范围。对于 Python 打包,语言文档和打包指南比任意的教程更适合作为起点。.

response = client.responses.create(
    preset="fast",
    input=(
 "一个小型 Python 项目应如何使用虚拟环境"
 "并管理依赖项?请引用您所遵循的指南。"
    ),
    tools=[
 {
 "type": "web_search",
 "filters": {
 "search_domain_filter": [
 "docs.python.org",
                    "packaging.python.org",
 ]
 },
 }
    ],
)

该过滤器应位于网页搜索工具的配置中。迁移文档中还描述了 search_recency_filter 适用于对时间敏感的问题。当问题涉及最新发布的消息或新闻时,应采用“近期性”原则;如果领域和日期范围过于狭窄,可能会导致可用证据不足。.

若要询问过去一个月内的发布情况,请添加 "search_recency_filter": "month" 旁边 search_domain_filter. 在虚拟环境示例中请勿包含此内容:稳定版文档的发布日期可能较早。如果您从预设模型切换到直接选择的模型,请明确包含网络搜索工具。.

在开发过程中,请对比经过过滤和未经过滤的结果。如果答案发生变化,请记录原因:过滤器可能会移除有用的上下文,也可能移除了那些干扰模型的低权威页面。这是一项质量决策,并不保证剩下的每个页面都是正确的。.

如果您的应用程序只需要带排名的链接和摘要,请调用 搜索 API 并亲自进行合成。这种分离可以使审查和缓存变得更加容易。如需与谷歌进行更广泛的比较,请参阅 Perplexity 与 Google 的区别.

第 5 步:保存包含可点击来源的完整答案

将以下内容另存为 perplexity_tutorial.py. 它是一个自包含的工具:包含源辅助程序,应用 Python 文档域过滤器,将匹配的引用标记转换为链接,在不丢失 ID 的情况下对重复的 URL 进行分组,并将完整的 SDK 响应与 Markdown 一起保存。.

from pathlib import Path
from collections import defaultdict
from urllib.parse import urlsplit
import json
import re

QUESTION = (
    "How should a small Python project use virtual environments "
    "and manage dependencies?"
)
# Supports the documented [1] and [web:1] forms in prose answers.
CITATION_RE = re.compile(r"(?<!!)\[(?:web:)?(\d+)\](?!\()")

def field(obj, name, default=None):
    return obj.get(name, default) if isinstance(obj, dict) else getattr(obj, name, default)

def source_index(output):
    sources = {}
    for item in output or []:
        if field(item, "type") != "search_results":
            continue
        for result in field(item, "results", []) or []:
            sid, url = field(result, "id"), field(result, "url")
            if sid is None:
                continue
            key = str(sid)
            if key in sources and field(sources[key], "url") != url:
                raise ValueError(f"Conflicting URLs for source ID {key}")
            sources[key] = result
    return sources

def safe_url(value):
    if not isinstance(value, str):
        return None
    parsed = urlsplit(value)
    if parsed.scheme not in ("http", "https") or not parsed.netloc:
        return None
    # Protect a Markdown angle-bracket destination.
    return value.replace("<", "%3C").replace(">", "%3E").replace(" ", "%20")

def md_label(value):
    return re.sub(r"([\\\[\]<>])", r"\\\1", str(value).replace("\n", " "))

def export_markdown(answer, output, question=QUESTION):
    sources = source_index(output)
    cited = list(dict.fromkeys(CITATION_RE.findall(answer)))
    missing = [
        sid for sid in cited
        if sid not in sources or not safe_url(field(sources[sid], "url"))
    ]
    def link(match):
        sid = match.group(1)
        url = safe_url(field(sources.get(sid, {}), "url"))
        return f"[{match.group(0)[1:-1]}](<{url}>)" if url else match.group(0)

    # Keep every ID when the same URL appears under different IDs.
    grouped = defaultdict(list)
    titles = {}
    for sid in cited:
        source = sources.get(sid, {})
        url = safe_url(field(source, "url"))
        if url:
            grouped[url].append(sid)
            titles.setdefault(url, field(source, "title") or url)

    lines = ["# Source-grounded answer", "", question, "",
             CITATION_RE.sub(link, answer), "", "## Cited sources", ""]
    for url, ids in grouped.items():
        lines.append(f"- IDs {', '.join(ids)}: [{md_label(titles[url])}](<{url}>)")
    if missing:
        lines.append("- Unmatched or unusable source IDs: " + ", ".join(missing))
    if not cited:
        lines.append("- No recognized inline citations; evidence not verified.")
    lines.extend(["", "Source links require review; matching IDs does not verify claims."])
    return "\n".join(lines) + "\n"

def main():
    from perplexity import Perplexity
    response = Perplexity().responses.create(
        preset="fast",
        input=QUESTION,
        tools=[{"type": "web_search", "filters": {
            "search_domain_filter": ["docs.python.org", "packaging.python.org"]
        }}],
    )
    answer = response.output_text or ""
    if not answer.strip():
        raise RuntimeError("No answer text returned; inspect response status and errors.")
    Path("perplexity-response.json").write_text(
        response.model_dump_json(indent=2), encoding="utf-8"
    )
    Path("perplexity-answer.md").write_text(
        export_markdown(answer, response.output), encoding="utf-8"
    )
    print("Saved perplexity-answer.md and perplexity-response.json")

if __name__ == "__main__":
    main()

运行 python perplexity_tutorial.py 从你的项目目录中。它会写入 perplexity-answer.md 和 perplexity-response.json 将这些文件保存到该位置,并用它们替换之前同名的文件。Markdown 文件包含问题、相关链接的答案、引用来源以及任何未匹配的 ID。JSON 文件则保存返回的输出结果及其使用情况,以便进行诊断。.

该解析器针对散文中已记录的单标记形式。它并非一个完整的 Markdown 解析器:如果您的应用程序需要处理任意格式的 Markdown、代码示例或引用,例如 [1,2], 添加一个支持该格式的语法感知渲染器及其测试用例。不要在不报错的情况下对不熟悉的标记进行重新解释。.

检查所链接的页面是否支持该答案

在此示例中,请核实所引用的文档是否确实解释了环境隔离和依赖项安装。Python 主页的链接不如相关文档部分有用。如果某个答案推荐了特定的命令,请在运行之前先确认其操作系统和 Python 版本。Mark 认为所引用的文本无法支持将该问题标记为“未解决”。.

根据需要添加流式或结构化输出

流媒体

流式传输可改善聊天界面的感知延迟。代理迁移指南中记录了诸如以下这类文本增量事件: response.output_text.delta. 在增量数据到达时立即渲染,但也要收集最终的响应项,以便在答案生成完成后,UI 能够显示来源列表。仅靠文本流本身并不构成来源列表。.

以下内容仅供参考。请保留首个完整源记录的非流式导出;在生产环境的流式实现中,还必须收集工具/输出事件,并处理中断或失败的运行。.

stream = client.responses.create(
    preset="fast", input=question, stream=True
)
for event in stream:
    if event.type == "response.output_text.delta":
 print(event.delta, end="", flush=True)

结构化输出

当下游代码需要诸如以下字段时,请使用结构化响应: 答案, confidence_note 和 后续问题. 将源 ID 作为单独字段保留,或保留 Agent 的原始输出,以免模式掩盖相关证据。在工作流中依赖该模式之前,请先使用您自己的测试用例对模式进行验证。.

迁移参考保留了 response_format 与 type: "json_schema" 用于结构化输出。定义必填字段,并在适当情况下禁止出现意外属性。模式有效性检查关注的是结构,而非真实性:源ID仍需能解析为实际返回的记录,且由模型生成的置信度标签并非准确率指标。.

Perplexity API 费用及常见错误

Perplexity的官方定价页面, ,查阅于2026年9月28日,该规则将代理模型令牌与工具调用区分开来。以下是USD工具/搜索费用。该 快 代理预设和 search_type: "fast" 这些是不同的配置选项;请勿根据预设名称推断搜索速率。.

可计费操作每股美元每1,000美元
代理标准网页搜索$0.0025$2.50
代理快速搜索调用$0.001$1.00
代理 URL 获取$0.0005$0.50
搜索 API 请求成功$0.005$5.00
使用 Fast Search 的搜索 API$0.001$1.00
Perplexity的官方定价表,其中列出了Agent工具调用费用以及每1,000次请求的搜索API费用。.

例如 1,000 次标准网页搜索调用加上 1,000 次 URL 获取的费用为 $3.00 刀具费用 ($2.50 + $0.50),不包括模型令牌或其他费用。这是基于假设的工作负载,并非本教程中测得的实际成本。单个代理请求可能会调用多个工具。如有可用,请检查 使用量.成本.总成本 在已完成的答复上。.

症状首先应检查什么
401 或 403环境变量名称、密钥有效性、账户访问权限以及请求是否已到达当前端点。.
计费或配额错误API 配额、支付设置、模型/工具费用及账户限额。Perplexity 消费者套餐并不自动包含 API 配额。.
429速率限制和重试行为。应采用有界指数退避算法,并避免盲目重发已成功处理的请求。.
超时网络路径、提示框大小、工具数量和客户端超时设置。如果 SDK 提供了请求 ID,则记录该 ID,但切勿记录密钥。.
该答案没有匹配的来源检查原料 response.output, ,引用格式和来源ID;应将该答案标记为“未核实”,而非捏造链接。.

搜索 API 会对成功的请求进行计费,包括那些未返回任何结果的请求;其请求价格不包含额外的代币费用。代理成本取决于模型代币和工具。在比较答复工作流与纯搜索工作流时,请将这些计费单位区分开来。.

若要比较 API 预算,请参阅我们的 Perplexity API 费用指南 提供了背景信息,而当前费率的权威来源仍是官方定价页面。.

从旧版 Sonar 教程过渡

许多搜索结果仍显示旧版的“聊天补全”图标。客服人员迁移指南采用了直接的概念映射。如果您正在比较消费者模型标签与 API 预设,请参阅我们关于 LLM Perplexity 的用途 提供了背景信息,但不能替代 Agent API 文档。.

较早的声呐模式代理 API 模式
信息输入
模型预设
choices[0].message.content输出文本
过时的引用数组假设搜索结果 输出项与基于ID的匹配
请求中的搜索参数tools=[{"type":"web_search","filters":{...}}]

阅读直播 迁移概述 和 迁移详情 在修改生产代码之前。预设的映射仅作为起点,并不保证新旧模型在质量、延迟或成本方面完全一致。.

常见问题

Perplexity API 是免费的吗?

根据当前的快速入门和定价文档,API 采用按量付费模式。请不要以为消费者订阅、试用或促销积分就能让每次 API 调用都免费。.

使用该 API 是否需要 Perplexity Pro?

API 访问权限和消费者 Pro 套餐是两个独立的产品。请为计划使用的开发者账户创建 API 凭据,并查看 API 账单信息。.

我应该使用 Agent API 还是 Search API?

当您需要一个附有来源的完整、有依据的答案时,请选择“代理”。当您的应用需要自行处理排序、筛选和综合时,请选择“搜索”。如果您需要对每个生成步骤进行严格控制,可以将“搜索”与您自己的模型结合使用。.

我可以在 JavaScript 中调用 Perplexity 吗?

是的。请使用上文提到的服务器端 Node.js 示例或官方 JavaScript SDK。将密钥保存在服务器上。在读取原始 JSON 时,请检查类型化的输出项,并应用相同的源 ID 映射规则。.

Perplexity的引用是否一定正确?

不。引用仅告知你该答案指向的是哪个检索结果。你的申请或评审人仍需核查该页面的时效性、权威性,以及该页面是否确实支持该论点。.

为什么我的解析器没有找到任何来源?

检查原始输出项的类型,确认网络搜索是否已执行,并检查您的正则表达式是否与预设的引用格式匹配。如果未出现标记,请将答案保存为“未验证”,并调查该请求,而不是添加一个猜测的链接。.

GlobalGPT 能否替代 Perplexity API 密钥?

GlobalGPT 是一个面向日常 AI 应用的全能型 AI 工作区。其订阅和模型访问与 Perplexity 开发者账户、API 密钥及 API 积分是分开的;本 Python 教程使用的是开发者账户。.

一份实用的发布检查清单

  • 创建服务器端密钥并确认 API 计费。.
  • 运行精简版 快 在添加过滤器或开始流式传输之前,请先提交请求。.
  • 请保存完整的回答内容,而不仅仅是可见的答案文本。.
  • 将引用标记与返回的来源ID进行匹配,并对未匹配的标记进行标记。.
  • 检查所引用的页面,以确认其对主张的支持性、时效性以及是否存在重复的URL。.
  • 部署前,请重新检查生产环境代理、定价及迁移文档。.

现在,您已经掌握了实现可靠的 Perplexity API 集成的核心模式:提出一个针对性问题,让代理 API 进行搜索,将答案与证据关联在一起,并确保每条引用都能被追溯。在此基础上,围绕相同的源 ID 工作流,添加缓存、重试以及您自己的审核规则。.

分享帖子:

相关帖子