可易

优化客服智能体的成本与质量(中)

可易团队阅读约 17 分钟

说明提示缓存如何复用稳定前缀,以及如何把质量保证和打标移出同步路径,并按场景选择架构。

目录

优化第 3 轮:提示缓存

每个支持请求都包含相同的核心指令、政策规则、工具定义和回复模式。提示缓存(prompt caching)让 API 在工单之间复用这份共享上下文,减少重复处理并降低输入 Token 成本。客户特有细节,例如订单号、账户信息和检索到的记录,应当出现在共享前缀之后。

提示缓存在模型代际之间有变化。使用 gpt-5.4-mini 时,API 会自动识别重复前缀,即使客户特有细节改变,也可以复用共享的支持上下文。写入新前缀不会另收缓存写入费。保持工具定义一致,并用 tool_choice.allowed_tools 控制哪些工具可用,同时不改变共享工具列表。

GPT-5.6 引入两项变化:缓存写入会计费,开发者可以明确选择提示中哪一部分应当被缓存。使用 gpt-5.6-luna、gpt-5.6-terra 或 gpt-5.6-sol 时,默认缓存断点放在最新消息之后。如果这条消息在工单之间变化,最长的缓存前缀可能对不上。隐式模式仍然可以复用更早的合格消息结尾,包括最初的开发者消息块。因为把内容写入缓存的价格是正常输入 Token 价格的 1.25 倍,反复缓存这些独特消息可能增加成本,却产生不了有用的复用。

例如,两张订单状态工单可以共享相同的支持指令、政策规则和工具,尽管一张询问订单 O-1001,另一张询问订单 O-2002。对 GPT-5.6,把共享操作手册放在开发者消息的 input_text 块中,并在订单特有细节之前用 prompt_cache_breakpoint={"mode": "explicit"} 标记其结尾。顶层 instructions 不能包含断点。把 prompt_cache_options 设为显式模式并使用 ttl="30m",两次请求使用同一个 prompt_cache_key,例如 support_order_status_v1。当前缀合格且匹配时,第一张工单写入操作手册,后续工单可以按缓存输入费率复用它,同时正常处理各自的订单细节。

把 cached_tokens 和 cache_write_tokens 与延迟、每张已解决工单的成本放在一起比较。更多实现细节见提示缓存指南。

cache_friendly_request = {
    "model": "gpt-5.4-mini",
    "instructions": CACHE_FRIENDLY_PROMPT,
    "tools": SLIM_TOOLS,
    "tool_choice": allowed_tool_choice(["lookup_order"], mode="auto"),
    "prompt_cache_key": "support_order_status_v1",
    "reasoning": {"effort": "low"},
    "text": {"verbosity": "low"},
    "max_output_tokens": 300,
    "input": [
        {
            "role": "user",
            "content": json.dumps(
                {
                    "ticket_id": "T-001",
                    "customer_id": "C-100",
                    "message": "Where is order O-1001?",
                    "order_id": "O-1001",
                }
            ),
        }
    ],
}

print(json.dumps(cache_friendly_request, indent=2)[:2400] + "\n...")

{
  "model": "gpt-5.4-mini",
  "instructions": "Role: E-commerce support assistant.\nConstraints: Be concise, policy-compliant, and explicit about next steps. Do not disclose internal data.\nEscalate: duplicate charges, account access without verification, high-value disputes, and refunds outside the window.\nOutput shape: customer_message, resolution_type, escalate, internal_tags.\nTool contract: tool definitions are stable across requests; restrict callable tools with tool_choice.allowed_tools.\nVersion: support-agent-optimization-v1.\n\nStable support playbook digest:\n- Shipping delays: provide status, ETA, and tracking next steps; do not refund solely for short carrier delays.\n- Delivered-not-received: verify delivery details, ask the customer to check common locations, and start carrier trace steps when appropriate.\n- Damaged delivery: request photo evidence before offering replacement or refund; high-value damaged items require human review.\n- Refunds: standard returnable items are eligible within 30 days; outside-window or high-value disputes require human review.\n- Billing: duplicate-charge reports require billing review; acknowledge and escalate, but do not promise a completed refund.\n- Account access: when identity is not verified, escalate to account security; do not change credentials or contact information in chat.\n- Customer messages must be concise, policy-compliant, and explicit about next steps.\n- Internal notes, raw carrier payloads, CRM audit logs, and policy appendices must never be exposed to the customer.\nStable support playbook digest:\n- Shipping delays: provide status, ETA, and tracking next steps; do not refund solely for short carrier delays.\n- Delivered-not-received: verify delivery details, ask the customer to check common locations, and start carrier trace steps when appropriate.\n- Damaged delivery: request photo evidence before offering replacement or refund; high-value damaged items require human review.\n- Refunds: standard returnable items are eligible within 30 days; outside-window or high-value disputes require human review.\n- Billing: duplicate-charge reports require billing review; acknowledge and escalate, but do not promise a completed refund.\n- Account access: when identity is not verified, escalate to account security; do not change credentials or contact information in chat.\n- Customer messages must be
...

previous_response_id_example = '''
from support import STABLE_SUPPORT_PREFIX

first = client.responses.create(
    model="gpt-5.4-mini",
    instructions=STABLE_SUPPORT_PREFIX,
    tools=SLIM_TOOLS,
    input="Customer asks: Where is order O-1001?",
    prompt_cache_key="support_order_status_v1",
)

follow_up = client.responses.create(
    model="gpt-5.4-mini",
    previous_response_id=first.id,
    instructions=STABLE_SUPPORT_PREFIX,
    input="Customer follow-up: the carrier link is stale. What should I do?",
    prompt_cache_key="support_order_status_v1",
)
'''

print(previous_response_id_example)


from support import STABLE_SUPPORT_PREFIX

first = client.responses.create(
    model="gpt-5.4-mini",
    instructions=STABLE_SUPPORT_PREFIX,
    tools=SLIM_TOOLS,
    input="Customer asks: Where is order O-1001?",
    prompt_cache_key="support_order_status_v1",
)

follow_up = client.responses.create(
    model="gpt-5.4-mini",
    previous_response_id=first.id,
    instructions=STABLE_SUPPORT_PREFIX,
    input="Customer follow-up: the carrier link is stale. What should I do?",
    prompt_cache_key="support_order_status_v1",
)

caching_view = traces[traces["variant"].isin(["02_model_routing", "03_prompt_caching"])]
display(
    caching_view[
        [
            "variant_label",
            "ticket_id",
            "model",
            "input_tokens",
            "cacheable_prefix_tokens",
            "cached_tokens",
            "latency_input_tokens",
            "output_tokens",
            "cost_usd",
            "latency_s",
            "quality_score",
        ]
    ].style.format({"cost_usd": "${:.5f}", "quality_score": "{:.2f}", "latency_s": "{:.2f}"})
)

variant\_labelticket\_idmodelinput\_tokenscacheable\_prefix\_tokenscached\_tokenslatency\_input\_tokensoutput\_tokenscost\_usdlatency\_squality\_score
20Round 2: routingT-001gpt-5.4-mini106800106877$0.001231.560.98
21Round 2: routingT-002gpt-5.4-mini1139001139104$0.001411.720.98
22Round 2: routingT-003gpt-5.4-mini1162001162118$0.001491.870.98
23Round 2: routingT-004gpt-5.4-mini1150001150117$0.001471.870.98
24Round 2: routingT-005gpt-5.41119001119165$0.005362.480.99
25Round 2: routingT-006gpt-5.41166001166158$0.005372.490.99
26Round 2: routingT-007gpt-5.4-mini1179001179100$0.001421.730.98
27Round 2: routingT-008gpt-5.41180001180172$0.005622.490.99
28Round 2: routingT-009gpt-5.4-mini1166001166118$0.001491.870.98
29Round 2: routingT-010gpt-5.41123001123165$0.005372.480.99
30Round 3: cachingT-001gpt-5.4-mini22671779177993377$0.000931.540.98
31Round 3: cachingT-002gpt-5.4-mini2338177917791004104$0.001111.700.98
32Round 3: cachingT-003gpt-5.4-mini2361177917791027118$0.001191.850.98
33Round 3: cachingT-004gpt-5.4-mini2349177917791015117$0.001171.840.98
34Round 3: cachingT-005gpt-5.4231817791779984165$0.004352.450.99
35Round 3: cachingT-006gpt-5.42365177917791031158$0.004372.460.99
36Round 3: cachingT-007gpt-5.4-mini2378177917791044100$0.001121.700.98
37Round 3: cachingT-008gpt-5.42379177917791045172$0.004612.470.99
38Round 3: cachingT-009gpt-5.4-mini2365177917791031118$0.001191.850.98
39Round 3: cachingT-010gpt-5.4232217791779988165$0.004362.460.99

优化第 4 轮:拆分工作流

把分类、必要查询、解决或升级决策,以及客户回复留在同步路径上。当质量保证、标签、内部摘要、审计和报告不改变即时结果时,把它们移到后续工作。

默认或优先处理可以服务对延迟敏感的请求。Flex 用更低成本换更慢的响应和偶尔的资源不可用;确认模型支持,并处理超时或容量不可用。Batch 适合完成窗口为 24h 的离线作业。后台模式使请求异步,但本身不提供价格折扣。

sync_request = {
    "model": "gpt-5.4-mini",
    "instructions": CACHE_FRIENDLY_PROMPT,
    "tools": SLIM_TOOLS,
    "tool_choice": allowed_tool_choice(["lookup_order", "lookup_policy"], mode="auto"),
    "input": "Customer says order O-1002 arrived cracked. Resolve or escalate.",
    "reasoning": {"effort": "low"},
    "text": {"verbosity": "low"},
    "max_output_tokens": 260,
    "service_tier": "default",
    "prompt_cache_key": "support_damaged_delivery_v1",
}

background_flex_request = background_followup_request(EVAL_SET[1])

print("Synchronous customer-facing request:")
print(json.dumps(sync_request, indent=2)[:1800] + "\n...")
print("\nFollow-up flex request:")
print(json.dumps(background_flex_request, indent=2)[:1600] + "\n...")

Synchronous customer-facing request:
{
  "model": "gpt-5.4-mini",
  "instructions": "Role: E-commerce support assistant.\nConstraints: Be concise, policy-compliant, and explicit about next steps. Do not disclose internal data.\nEscalate: duplicate charges, account access without verification, high-value disputes, and refunds outside the window.\nOutput shape: customer_message, resolution_type, escalate, internal_tags.\nTool contract: tool definitions are stable across requests; restrict callable tools with tool_choice.allowed_tools.\nVersion: support-agent-optimization-v1.\n\nStable support playbook digest:\n- Shipping delays: provide status, ETA, and tracking next steps; do not refund solely for short carrier delays.\n- Delivered-not-received: verify delivery details, ask the customer to check common locations, and start carrier trace steps when appropriate.\n- Damaged delivery: request photo evidence before offering replacement or refund; high-value damaged items require human review.\n- Refunds: standard returnable items are eligible within 30 days; outside-window or high-value disputes require human review.\n- Billing: duplicate-charge reports require billing review; acknowledge and escalate, but do not promise a completed refund.\n- Account access: when identity is not verified, escalate to account security; do not change credentials or contact information in chat.\n- Customer messages must be concise, policy-compliant, and explicit about next steps.\n- Internal notes, raw carrier payloads, CRM audit logs, and policy appendices must never be exposed to the customer.\nStable support playbook digest:\n- Shipping delays: provide status, ETA, and tracking next steps; do not refund solely for short carrier delays.\n- Delivered-not-received: verify delivery details, ask the customer to check common location
...

Follow-up flex request:
{
  "model": "gpt-5.4-nano",
  "input": "{\"ticket\": {\"ticket_id\": \"T-002\", \"customer_id\": \"C-200\", \"message\": \"My blender arrived cracked. Order O-1002. Can you replace it?\", \"intent\": \"damaged_delivery\", \"order_id\": \"O-1002\", \"risk\": \"medium\", \"difficulty\": \"routine_policy\", \"must_escalate\": false, \"expected_policy\": \"damaged_delivery\", \"expected_tools\": [\"lookup_order\", \"lookup_policy\"], \"expected_action\": \"request_photo_then_offer_replacement\", \"expected_resolution_type\": \"resolved_next_step\", \"expected_customer_response_contains\": [\"photo\", \"replacement\"], \"forbidden_response_claims\": [\"refund completed\", \"no photo needed\"]}, \"policy\": \"If damage is reported within 7 days of delivery, ask for a photo and offer replacement or refund after evidence is collected. High-value damaged items over $1,000 require human review before promising a refund or replacement.\"}",
  "reasoning": {
    "effort": "low"
  },
  "text": {
    "verbosity": "low"
  },
  "max_output_tokens": 160,
  "service_tier": "flex"
}
...

batch_requests = []
for ticket in EVAL_SET:
    batch_requests.append(
        {
            "custom_id": f"qa-{ticket['ticket_id']}",
            "method": "POST",
            "url": "/v1/responses",
            "body": {
                "model": "gpt-5.4-nano",
                "instructions": "Return concise internal support QA tags and a one-sentence summary.",
                "input": json.dumps(ticket),
                "reasoning": {"effort": "low"},
                "text": {"verbosity": "low"},
                "max_output_tokens": 160,
            },
        }
    )

from pathlib import Path

Path("outputs").mkdir(exist_ok=True)
batch_file_path = "outputs/nightly_support_qa_batch.jsonl"
with open(batch_file_path, "w") as f:
    f.writelines(json.dumps(row) + "\n" for row in batch_requests)

print(f"Wrote {len(batch_requests)} example batch rows to {batch_file_path}")
print(json.dumps(batch_requests[0], indent=2))

Wrote 10 example batch rows to outputs/nightly_support_qa_batch.jsonl
{
  "custom_id": "qa-T-001",
  "method": "POST",
  "url": "/v1/responses",
  "body": {
    "model": "gpt-5.4-nano",
    "instructions": "Return concise internal support QA tags and a one-sentence summary.",
    "input": "{\"ticket_id\": \"T-001\", \"customer_id\": \"C-100\", \"message\": \"Where is order O-1001? It was supposed to arrive yesterday.\", \"intent\": \"order_status\", \"order_id\": \"O-1001\", \"risk\": \"low\", \"difficulty\": \"simple_lookup\", \"must_escalate\": false, \"expected_policy\": \"shipping\", \"expected_tools\": [\"lookup_order\"], \"expected_action\": \"provide_status_eta\", \"expected_resolution_type\": \"resolved\", \"expected_customer_response_contains\": [\"in transit\", \"tomorrow\"], \"forbidden_response_claims\": [\"refund completed\", \"replacement opened\"]}",
    "reasoning": {
      "effort": "low"
    },
    "text": {
      "verbosity": "low"
    },
    "max_output_tokens": 160
  }
}

batch_submission_example = '''
batch_input_file = client.files.create(
    file=open(batch_file_path, "rb"),
    purpose="batch",
)

batch = client.batches.create(
    input_file_id=batch_input_file.id,
    endpoint="/v1/responses",
    completion_window="24h",
    metadata={"description": "nightly support QA tags"},
)
'''

print(batch_submission_example)


batch_input_file = client.files.create(
    file=open(batch_file_path, "rb"),
    purpose="batch",
)

batch = client.batches.create(
    input_file_id=batch_input_file.id,
    endpoint="/v1/responses",
    completion_window="24h",
    metadata={"description": "nightly support QA tags"},
)

split_view = traces[traces["variant"].isin(["03_prompt_caching", "04_split_workflow"])]
display(
    split_view[
        [
            "variant_label",
            "ticket_id",
            "model",
            "tool_calls",
            "sync_tokens",
            "total_tokens",
            "background_tokens",
            "latency_s",
            "sync_cost_usd",
            "background_cost_usd",
            "cost_usd",
            "quality_score",
        ]
    ].style.format(
        {
            "sync_cost_usd": "${:.5f}",
            "background_cost_usd": "${:.5f}",
            "cost_usd": "${:.5f}",
            "quality_score": "{:.2f}",
            "latency_s": "{:.2f}",
        }
    )
)

variant\_labelticket\_idmodeltool\_callssync\_tokenstotal\_tokensbackground\_tokenslatency\_ssync\_cost\_usdbackground\_cost\_usdcost\_usdquality\_score
30Round 3: cachingT-001gpt-5.4-mini12552255201.54$0.00093$0.00000$0.000930.98
31Round 3: cachingT-002gpt-5.4-mini22650265001.70$0.00111$0.00000$0.001110.98
32Round 3: cachingT-003gpt-5.4-mini32689268901.85$0.00119$0.00000$0.001190.98
33Round 3: cachingT-004gpt-5.4-mini32673267301.84$0.00117$0.00000$0.001170.98
34Round 3: cachingT-005gpt-5.432689268902.45$0.00435$0.00000$0.004350.99
35Round 3: cachingT-006gpt-5.432735273502.46$0.00437$0.00000$0.004370.99
36Round 3: cachingT-007gpt-5.4-mini22691269101.70$0.00112$0.00000$0.001120.98
37Round 3: cachingT-008gpt-5.432769276902.47$0.00461$0.00000$0.004610.99
38Round 3: cachingT-009gpt-5.4-mini32697269701.85$0.00119$0.00000$0.001190.98
39Round 3: cachingT-010gpt-5.432696269602.46$0.00436$0.00000$0.004360.99
40Round 4: split workflowT-001gpt-5.4-mini1228728675801.10$0.00071$0.00011$0.000820.98
41Round 4: split workflowT-002gpt-5.4-mini2238129405591.26$0.00087$0.00010$0.000970.98
42Round 4: split workflowT-003gpt-5.4-mini3241829785601.41$0.00094$0.00010$0.001050.98
43Round 4: split workflowT-004gpt-5.4-mini3240129425411.41$0.00092$0.00010$0.001030.98
44Round 4: split workflowT-005gpt-5.43241329565432.02$0.00346$0.00010$0.003560.99
45Round 4: split workflowT-006gpt-5.43245930195602.03$0.00348$0.00010$0.003580.99
46Round 4: split workflowT-007gpt-5.4-mini2242230236011.27$0.00088$0.00011$0.000990.98
47Round 4: split workflowT-008gpt-5.43249230635712.03$0.00371$0.00010$0.003810.99
48Round 4: split workflowT-009gpt-5.4-mini3242629885621.41$0.00095$0.00010$0.001050.98
49Round 4: split workflowT-010gpt-5.43242029625422.02$0.00347$0.00010$0.003570.99

权衡与场景映射

没有普遍最佳的配置。最优点取决于流量形态、对客户的承诺、政策风险、缓存命中率、工具延迟、可观测性成熟度,以及有多少工作可以移出同步路径。

支持智能体的重要权衡是:

约束把你推向需要留意
高政策或账户安全风险高风险路径用更大的模型、更严格的升级、评判器评测过度升级会损害客户体验和支持产能
高工单量且工作流重复稳定前缀、提示缓存、更小的模型、后续工作用 Batch大前缀上的缓存未命中会增加延迟
低延迟的客户承诺短提示、精简工具载荷、路由、异步后续工作如果任务本来就简单,过多路由会增加开销
严格的成本目标分诊和常规路径用 nano/mini、输出上限、离线工作用 flex 或 Batch如果质量门很弱,只按成本调优会去掉防护
工具混乱或数据不可靠更少的工具调用、经过校验的载荷、回退、工具失败时升级盲目缩小上下文会去掉政策决策所需的证据
高端或受监管的支持更高的质量下限、更低的升级阈值、更多离线审计元数据更多同步复核会增加延迟和成本
季节性突发对缓存友好的请求、感知队列的服务层级、异步分析如果路由键过于碎片化,高峰流量会降低缓存效果

下表把常见运行场景映射到候选配置。把它当作设计辅助:选择能通过该场景质量、延迟和运行约束的最便宜配置。

候选架构组合

这张表比较同一客户支持用例的候选智能体架构。它使用笔记本的模拟评测集和确定性空跑模拟指标,而不是实时 API 轨迹。用相对差异理解权衡;做部署决策之前,用生产轨迹数据替换这些指标。

from scenarios import (
    ARCHITECTURE_OPTIONS,
    OPERATING_SCENARIOS,
    architecture_metrics,
    scenario_fit_score,
)

architecture_rows = [
    {"architecture": key, **option, **architecture_metrics(key, summary)}
    for key, option in ARCHITECTURE_OPTIONS.items()
]
architecture_df = pd.DataFrame(architecture_rows)
print("Table: Candidate architecture combinations (mock eval set + deterministic dry-run metrics)")
display(
    architecture_df[
        [
            "label",
            "models",
            "tools",
            "cache",
            "workflow",
            "quality",
            "policy_compliance",
            "p50_latency_s",
            "monthly_cost_at_100k_tickets",
            "best_for",
        ]
    ].style.format(
        {
            "quality": "{:.2f}",
            "policy_compliance": "{:.0%}",
            "p50_latency_s": "{:.2f}",
            "monthly_cost_at_100k_tickets": "${:,.0f}",
        }
    )
)

Table: Candidate architecture combinations (mock eval set + deterministic dry-run metrics)

labelmodelstoolscacheworkflowqualitypolicy\_compliancep50\_latency\_smonthly\_cost\_at\_100k\_ticketsbest\_for
0One broad agentgpt-5.4 for every stepall tools exposednoneall work synchronous0.5110%4.88$3,813prototype smell test only
1Controlled full modelgpt-5.4 for resolutionallowed tools by routed pathnonesome follow-up still synchronous0.98100%2.32$512high-risk launch or low confidence in routing/model mix
2Routed, no cachenano triage, mini routine, gpt-5.4 high riskallowed tools by routed pathnonesome follow-up still synchronous0.98100%1.87$302mixed ticket queues with moderate repeat traffic
3Routed split, no cachenano triage/tags, mini routine, gpt-5.4 high riskallowed tools by routed pathnonecustomer path sync, QA/tags/reporting async0.98100%1.57$285low-repeat queues that still need async follow-up work
4Routed + cachenano triage, mini routine, gpt-5.4 high riskstable full tool list plus allowed\_toolsstable playbook prefixsome follow-up still synchronous0.98100%1.85$244high-volume repeated workflows with good cache locality
5Balanced split workflownano triage/tags, mini routine, gpt-5.4 high riskstable full tool list plus allowed\_toolsstable playbook prefixcustomer path sync, QA/tags/reporting async0.98100%1.41$204most mature repeated-workflow support deployments

场景最优点

这张表把常见的真实运行场景映射到得分最高的架构组合。场景约束是为演示而模拟的,架构指标来自上面的空跑模拟。在生产环境中,用你的支持服务级别协议(SLA)、预算、政策风险阈值和观察到的缓存命中率替换这些约束。

fit_rows = [
    scenario_fit_score(scenario, option_key, summary)
    for scenario in OPERATING_SCENARIOS
    for option_key in ARCHITECTURE_OPTIONS
]
fit_df = pd.DataFrame(fit_rows)

best_fit = (
    fit_df.sort_values(["scenario", "score", "monthly_cost_at_100k_tickets"], ascending=[True, False, True])
    .groupby("scenario", sort=False)
    .head(1)
    .reset_index(drop=True)
)

scenario_context = pd.DataFrame(OPERATING_SCENARIOS)[
    [
        "scenario",
        "description",
        "quality_floor",
        "policy_floor",
        "p50_latency_target_s",
        "monthly_budget_100k_usd",
        "needs_async",
        "cache_locality",
    ]
]

best_fit_view = best_fit.merge(scenario_context, on="scenario")

print("Table: Recommended sweet spot by scenario (mock constraints + dry-run architecture metrics)")
display(
    best_fit_view[
        [
            "scenario",
            "description",
            "label",
            "score",
            "quality",
            "quality_floor",
            "policy_compliance",
            "policy_floor",
            "p50_latency_s",
            "p50_latency_target_s",
            "monthly_cost_at_100k_tickets",
            "monthly_budget_100k_usd",
            "cache_locality",
            "failed_constraints",
        ]
    ].style.format(
        {
            "quality": "{:.2f}",
            "quality_floor": "{:.2f}",
            "policy_compliance": "{:.0%}",
            "policy_floor": "{:.0%}",
            "p50_latency_s": "{:.2f}",
            "p50_latency_target_s": "{:.2f}",
            "monthly_cost_at_100k_tickets": "${:,.0f}",
            "monthly_budget_100k_usd": "${:,.0f}",
        }
    )
)

Table: Recommended sweet spot by scenario (mock constraints + dry-run architecture metrics)

scenariodescriptionlabelscorequalityquality\_floorpolicy\_compliancepolicy\_floorp50\_latency\_sp50\_latency\_target\_smonthly\_cost\_at\_100k\_ticketsmonthly\_budget\_100k\_usdcache\_localityfailed\_constraints
0Account and billing sensitive queueRisky account recovery and duplicate-charge workflows dominate.Routed split, no cache130.980.98100%100%1.572.80$285$750mediumnone
1Early pilotLow volume, quality learning matters more than unit cost.Routed, no cache130.980.94100%98%1.873.00$302$800lownone
2High-volume routine ecommerceMany repeated order, return, and damage workflows.Balanced split workflow130.980.96100%99%1.412.00$204$300highnone
3Low-repeat long tailMany rare ticket types; cache hit rate is uncertain.Routed split, no cache130.980.96100%99%1.572.50$285$450lownone
4Peak sale burstLatency and cost matter during temporary traffic spikes.Balanced split workflow130.980.95100%99%1.411.80$204$250highnone
5Premium supportHigher customer value, lower tolerance for wrong actions.Routed split, no cache130.980.98100%100%1.572.50$285$650mediumnone

一个场景的完整组合图

这张表展示一个模拟场景 Low-repeat long tail 的全部架构选项。放在这里是为了让权衡可见,而不是把一切藏在单一最佳选择后面。数字仍然是模拟的;重点是说明当缓存局部性低时,重度依赖缓存的设计为什么没那么有吸引力。

# Show the full combination map for one scenario so tradeoffs are visible, not hidden behind the best pick.
scenario_to_inspect = "Low-repeat long tail"
combo_map = fit_df[fit_df["scenario"] == scenario_to_inspect].sort_values("score", ascending=False)

print(f"Table: Full architecture ranking for {scenario_to_inspect} (mock scenario + dry-run metrics)")
display(
    combo_map[
        [
            "label",
            "score",
            "quality",
            "policy_compliance",
            "p50_latency_s",
            "monthly_cost_at_100k_tickets",
            "failed_constraints",
        ]
    ].style.format(
        {
            "quality": "{:.2f}",
            "policy_compliance": "{:.0%}",
            "p50_latency_s": "{:.2f}",
            "monthly_cost_at_100k_tickets": "${:,.0f}",
        }
    )
)

Table: Full architecture ranking for Low-repeat long tail (mock scenario + dry-run metrics)

labelscorequalitypolicy\_compliancep50\_latency\_smonthly\_cost\_at\_100k\_ticketsfailed\_constraints
27Routed split, no cache130.98100%1.57$285none
26Routed, no cache100.98100%1.87$302async split
29Balanced split workflow90.98100%1.41$204cache locality
28Routed + cache60.98100%1.85$244async split, cache locality
25Controlled full model50.98100%2.32$512budget, async split
24One broad agent-140.5110%4.88$3,813quality, policy, latency, budget, async split

在这些模拟场景中,重复工作流偏向共享缓存前缀和异步后续处理。低重复队列可能偏向不使用缓存的路由拆分,而早期试点在路由可靠之前,可能有理由使用完整模型。

把这些排名当作一次设计练习。它们包含手工设定的约束和评分加成,因此高分并不能证明某个架构满足每一项要求。选择生产配置之前,检查 failed_constraints,并强制执行质量和政策门。

PRIMARY_SOURCE: https://developers.openai.com/cookbook/examples/agent_optimization/optimizing_agents_for_cost_and_quality

  • #提示缓存
  • #工作流拆分
  • #客服智能体
  • #成本优化
  • #架构选型
  • 投入回报

    优化客服智能体的成本与质量(上)

  • 投入回报

    AI 成本失控前,先给 Token 记账