如今大多数产品都带有 AI 功能:帮助页上的聊天助手、商店内的 AI 搜索、自动生成的商品描述、推荐面板。每一项都可能根据用户所在位置给出不同的回答,而团队在办公室测试时很少能发现这些差异。如果你的产品服务多个市场,按国家检查 AI 输出应该与你的 AI 和机器学习工作以及发布测试放在一起,而不是等到某个市场投诉后才做。
本文介绍 AI 输出为什么会因国家而异、要检查什么、如何让测试请求看起来像当地用户,以及如何比较那些从不逐字相同的回答。
为什么 AI 输出会因国家而异
大多数差异来自模型周围的产品,而不是模型本身:
- 位置作为上下文。 很多助手会把从 IP 读取的用户国家或城市加入提示词。一旦查询出错,就会针对错误的市场给出一个看似笃定的回答。
- 区域路由。 请求可能按地区发往不同的模型、版本或接口,通常是出于数据驻留的原因。两个市场在同一天可能运行着不同版本的模型。
- 功能开关。 AI 功能往往是按国家逐个上线的。一个在某个市场正常工作的按钮,在另一个市场可能缺失或无法使用。
- 政策和合规规则。 当地关于健康、金融、选举或年龄的规定,可能只在某些国家触发拒绝回答或免责声明。
- 检索。 当助手搜索网页、帮助中心或商品目录时,通常会按用户所在地区搜索,因此它引用的事实和产品也会变化。
其中第一项和最后一项取决于请求来自哪个 IP。这就是为什么只从一个地点测试会漏掉它们。
每个市场要检查什么
对你服务的每个市场,检查同一组属性:
| 检查项 | 可能出现的问题 |
|---|---|
| 语言 | 给日本用户用英语回答,或在一条回复中混用多种语言 |
| 货币和单位 | 给德国用户显示美元价格,用英里而不是公里 |
| 当地事实 | 该国的配送时间、节假日、税务规则或门店位置有误 |
| 功能可用性 | AI 功能被隐藏、报错,或显示”您所在的地区不可用”提示 |
| 政策行为 | 本应只在某个国家适用的拒绝回答或免责声明出现在所有地区,或者相反 |
| 产品和来源 | 推荐或引用了在该市场没有销售或与该市场无关的商品 |
| 格式 | 日期、数字和地址没有使用当地格式 |
其中有几项与传统的页面检查重叠。我们的大规模本地化 QA指南涵盖了文案、hreflang 和布局;这份清单则涵盖 AI 层额外带来的内容。
以当地用户身份测试
位置通常来自 IP,所以测试请求必须来自该市场。通过定向到目标国家的住宅代理发送请求,能让产品应用与当地真实用户相同的地区识别、功能开关和政策。数据中心 IP 段经常被 IP 数据库映射到错误的国家,或被置于机器人检测之后,这样得到的测试结果是该市场任何真实用户都不会看到的。
请求的其他部分也要与市场匹配:Accept-Language 请求头、时区以及浏览器的区域设置。使用英文浏览器的日本 IP 与使用日文浏览器的日本 IP 是两类不同的用户,两者都值得测试。我们关于匹配代理地理位置、时区和区域设置的文章解释了如何让这些信号保持一致。
对于多轮对话,用粘性会话让整段对话保持同一个 IP,这样产品就不会看到用户在两轮之间切换位置:
customer-USERNAME-country-jp-sid-chat-ja-01-ttl-600:PASSWORD
一个小型测试框架
下面的测试框架从多个市场向你的 AI 接口发送相同的提示词,检查的是属性而不是精确文本。请把接口地址和检查项替换成你自己的。
import requests
GATEWAY = "p.shifter.io:443"
USER, PASS = "USERNAME", "PASSWORD"
ENDPOINT = "https://app.example.com/api/assistant"
MARKETS = {
"de": {"lang": "de-DE", "currency": "€"},
"jp": {"lang": "ja-JP", "currency": "¥"},
"br": {"lang": "pt-BR", "currency": "R$"},
"us": {"lang": "en-US", "currency": "$"},
}
PROMPTS = ["How much is shipping for a 2 kg parcel?", "Recommend a laptop under my budget."]
RUNS = 3
def ask(country, lang, prompt, run):
proxy = f"http://customer-{USER}-country-{country}-sid-ai-{country}-{run}-ttl-600:{PASS}@{GATEWAY}"
r = requests.post(ENDPOINT, json={"message": prompt},
headers={"Accept-Language": lang},
proxies={"http": proxy, "https": proxy}, timeout=60)
return r.status_code, r.json().get("answer", "") if r.ok else ""
for country, m in MARKETS.items():
for prompt in PROMPTS:
hits = 0
for run in range(RUNS):
status, answer = ask(country, m["lang"], prompt, run)
if status == 200 and m["currency"] in answer:
hits += 1
print(country, prompt[:30], f"currency ok in {hits}/{RUNS} runs")
为上表的每一行添加一项检查:回复的语言检测器、每个市场在售商品的清单、地区性”不可用”提示的匹配规则。每个提示词都要运行多次,因为模型输出在每次运行之间都会变化;三次中有两次通过的检查是一个发现,而不是噪声。
把它纳入发布测试
- 每次更改模型、提示词或功能开关后都运行测试框架,而且要从每个市场运行,而不只是从默认地区。
- 为每个市场保留一组固定的提示词,由母语人士编写,包括当地客户真正会问的问题。
- 保存回答时附上国家、模型版本和时间,这样你就能区分模型变更和路由变更。
- 每周按国家复查拒绝回答的情况。 某个市场的拒绝率突然上升,通常指向某条政策规则或某个区域接口。
如果你的 AI 功能也出现在搜索中,同样的分市场方法也适用于监控 AI 搜索可见度,这时要关注的是其他助手在每个国家如何描述你。
总结
AI 输出是本地化的,因为模型周围的产品会读取用户位置并据此行动。从每个市场的住宅 IP 测试该市场,配合匹配的语言和区域设置,让多轮对话保持在同一个粘性 IP 上,并在多次运行中检查语言、货币、当地事实、功能可用性和拒绝回答等属性。每次发布都这样做,区域性的 AI 问题就不会再由客户最先发现。