AI也是无障碍?从辅助技术到AI应用的可访问性设计 📅 发布时间:2026/9/4 7:34:38 👁 浏览次数: 最近 Hacker News 上有一个提问很有意思既然无障碍法律已经要求网站、App 对读屏软件这类辅助技术开放为什么不同样扩大无障碍法律的适用边界把“使用 AI 的权利”也写进去这个问题初看像法学生式的思想实验但它背后藏着一个正在发生的技术变化AI 正在从“可选的效率工具”变成一部分人参与数字社会的基本通道。对很多残障用户来说AI 不是“锦上添花”而是“没有它就寸步难行”。如果一个盲人要理解一张复杂的产品截图以前的工具链是 OCR 加人工核对现在给多模态大模型发一句话就能得到结构化的描述如果一个手部运动受限的用户无法打字语音输入配合文本生成就是他的键盘。如果这种能力被付费墙、产品设计缺陷或模型偏见挡在外面那么把它理解为一种无障碍诉求其实是顺理成章的。本文不打算预测哪个国家、哪部法律会怎么修订那超出了技术博客的边界。我更想把这个问题翻译成工程师能动手的事当 AI 承担起辅助技术的角色前端语义、API 设计、模型输出和测试验收到底应该怎么改这篇文章会先讲清楚为什么“使用 AI 的权利”会成为一个真问题再拆解它落地时的四个技术断点最后给出一套可以照做的工程示例包含后端接口、前端无障碍接入、流式播报处理和效果验证。对正在做 AI 应用开发、Agent、大模型产品或信息系统无障碍改造的开发者来说这篇文章或许能帮你提前避开未来三到五年的合规与技术债。1. 当“使用 AI”成为一种无障碍诉求先看一个具体场景。一位全盲的办公室职员收到一张项目截图里面有几个图表和数据。传统读屏软件能读出按钮文字、标题层级但读不出“柱状图的趋势走向”也读不出“截图里的红色标注对应哪一行数据”。过去他只能求助同事或者把图片交给第三方人工描述服务等上几个小时。现在他可以把图片粘贴进支持视觉问答的 AI 对话框让模型告诉他图表的趋势、异常值和上下文。再看另一个场景。一位患有运动障碍的用户无法使用普通键盘过去他依赖眼动仪和慢速的逐字输入。现在如果系统内置了高质量的语音识别和语句补全他的输入效率能提升数倍但如果系统只提供纯文字聊天框不支持语音、不支持辅助开关他依然会被困在输入这一环。这些场景说明AI 对残障群体的意义和普通人完全不同。普通人用 AI 是省时间残障用户用 AI 是补障碍。当他们需要的是“读图”“听懂语音”“简化长文本”这类能力时AI 实际上已经承担了传统辅助技术的功能只是大家还没把它写进无障碍的法律与规范清单。所以那个 HN 提问真正有价值的并不是一个“应该不应该”的价值判断而是它提醒我们如果越来越多的社会服务把 AI 当成默认入口那 AI 服务的可访问性就不能只靠厂商自觉。过去无障碍法律要求的是“产品不要挡住辅助技术”现在的趋势是“产品里的 AI 能力本身要具备可访问性”。这种转变对开发团队意味着什么意味着今天你做的每一个 UI 设计、接口返回、流式渲染方案都可能成为明天验收清单上的一条硬指标。我自己的判断是法律条文会不会通过、什么时候通过不是工程师能决定的但“什么时候做无障碍 AI 改造”开发团队是可以决定的。迟到的无障碍改造一定比提前设计贵几倍因为在功能已经上线后再回填语义标签、重构接口返回格式几乎等于重做一遍。2. 先厘清概念无障碍、辅助技术与 AI 的三层关系要理解“无障碍与 AI”这个话题需要先把几个经常混用的词拆开。无障碍Accessibility常简写为 a11y指的是产品或服务能够让残障人士感知、操作和理解。它不等于“可用性”一个按钮做得再好看、点击区域再大如果读屏软件无法聚焦它在无障碍层面就是失败的。传统的信息无障碍标准比如 WCAG围绕四个原则展开可感知、可操作、可理解、健壮性。辅助技术Assistive TechnologyAT是用户用来访问产品的工具包括读屏软件 NVDA、JAWS、VoiceOver、TalkBack也包括屏幕放大器、替代键盘、眼动仪、开关控制设备等。无障碍法律的常见做法并不是强制所有人使用某种辅助技术而是要求产品不要阻碍这些技术发挥作用。这里就牵扯出一个容易被混淆的点AI 和辅助技术的关系有两种。第一种AI 功能可以内嵌到你的产品里让你的产品本身变得更容易访问。例如一个图片问答按钮、一个长文本“一键简化”按钮它们是无障碍功能。这种情形下法律的关注点是“AI 功能入口是否可操作、结果是否可理解”。第二种AI 服务可以被外部辅助技术调用成为辅助技术链路上的一环。例如读屏软件调用云端的图片描述 API替用户生成替代文本。这种情况下AI 不再是产品里的一个按钮而是一个被其他工具依赖的基础服务它需要稳定、可预期、输出规范否则所有下游辅助工具都会被带偏。无障碍法律的历史演进大致遵循一个规律从物理空间扩展到数字产品再逐步扩展到算法服务。各国对“数字产品”的约束范围已经在扩大。例如美国 ADA 相关的诉讼实践中网站和移动应用的可访问性已经成为重点欧盟的《欧洲无障碍法案》把服务也纳入了强制范围国内的《无障碍环境建设法》于 2023 年施行也明确将网站、移动互联网应用纳入信息无障碍的推进范围。不同法域的具体对象和执行强度不同但大方向一致数字产品负责任的时代已经来了。法域 / 标准主要对象与 AI 相关的信号WCAG / W3C 无障碍指南网站、Web 应用强调可感知、可操作、可理解、健壮性是自动化测试的重要依据美国 ADA 及相关诉讼公共场所、商业网站、App网站不可访问被起诉的案例增多AI 客服、AI 对话也开始被讨论欧盟《欧洲无障碍法案》产品与服务2025 年起逐步进入更强约束阶段中国《无障碍环境建设法》政务、公共生活、信息无障碍已从物理设施延伸到网站和移动应用相关配套技术要求还会细化需要说明上面的对比只是帮助理解趋势不是法律意见。真实的合规判断必须结合具体业务、法域和最新政策必要时应咨询专业法律人士。不过如果往前多看半步真正的争议点在于传统无障碍法律要求的是“让既有产品可被访问”而不是“保证每个公民都能使用某一种新技术”。AI 作为新一代通用能力是不是一种应当被保障的基础资源这个问题在法律上一时半会很难达成共识但它给工程侧的启发已经很清晰了做 AI 应用的时候不能只把残障用户当作“测试的一小类人群”而要把他们当成默认用户来设计。3. 为什么“写进法律”没那么简单四个技术断点如果只是谈理念“残障用户需要 AI”几乎没有人反对。但从法律条文走向技术验收中间隔着四个很实际的断点。理解这些断点能解释为什么立法迟迟没有跟上也能告诉你研发侧应该在哪里使劲。第一个是“判定断点”。什么叫“有权使用 AI”是指每个人都有权调用某一个公开大模型的 API还是指当服务商把 AI 作为主要客服入口时必须为无法使用 AI 的人保留人工通道两者的差异极大。法律条文通常只能写原则但 AI 模型、版本、价格、接口形态变化太快原则很难落地成一条可执行的验收标准。更实际的做法是倒过来不问“谁有权用 AI”而是问“一个残障用户在这条服务链路上能不能完成和非残障用户等价的动作”。第二个是“验证断点”。传统无障碍已经有 WCAG 之类的可测试标准自动化工具可以检查按钮是否有可访问名称、图片是否有替代文本、颜色对比度是否达标。但 AI 输出的正确性很难自动化验证。你无法用一个脚本断言“这次对图片的描述就一定是对的”因为模型是概率性的。你可以测试界面层“是否能聚焦、是否可点击”但测试不了“这次回答对这个用户是否有价值”。所以面向无障碍的 AI 系统除了常规单测还需要一套持续维护的评测集把真实场景里的图片、文本、方言语音都放进去每次模型升级都要跑一遍。第三个是“质量断点”。无障碍场景对 AI 错误更敏感。普通用户遇到模型幻觉笑一笑就过去了如果图片描述服务把一个红灯描述成“绿灯”盲人用户很可能因此做出错误判断。这要求 AI 产品在输出侧做额外的安全设计例如给出置信度提示、主动说明“图片某个区域模糊无法判断”以及提供人工复核渠道。模型本身达不到完美并不可怕可怕的是把不确定的内容包装成确定的事实。第四个是“责任断点”。当 AI 成为辅助技术的一部分后一旦出错谁负责是模型提供方、应用开发方还是部署运维方假如一个视障用户因为 AI 的错误描述错过了重要信息他应该找谁这个责任链条在传统软件里比较清晰在 AI 链路里则复杂得多。很多厂商担心的正是这种“兜底责任”不确定才不敢把无障碍 AI 当成正式承诺。这四个断点也是工程机会。我们无法替立法者决定规则但可以先建立技术上的可观测、可评测、可回滚机制。当一套 AI 功能既能产出结构化结果、又能给出不确定性说明、还能被读屏软件正常播报时它至少已经满足了未来合规的底层条件。4. AI 应用的可访问性架构从“产品无障碍”到“无障碍 AI 服务”把前面的讨论落到系统设计上可以把一个 AI 应用拆成三层输入层、模型层、输出层。每一层都有独立的可访问性问题团队的测试方法也应该分层做。输入层解决“用户怎么把问题交给 AI”。一个只有鼠标操作的大画布交互界面对键盘用户就是灾难一个只接受文字输入、不支持语音的服务对部分运动障碍用户也很不友好。做输入层时至少要保证所有操作都能用键盘完成表单控件有清晰的 label错误提示不用颜色作为唯一标识语音输入功能在嘈杂场景下有文字纠错入口。这里真正容易踩坑的地方是“语音输入”看似无障碍实际只对普通话标准、环境安静的用户友好遇到方言、口音、语速变化时识别率会断崖式下降。所以不要把语音当成唯一的无障碍输入方案要保留文字纠错和备用通道。模型层解决“AI 对不同用户的识别与理解是否公平”。常见问题包括语音模型对特定口音识别率低、视觉模型对少数族裔或非典型场景描述准确率偏低、文本模型生成内容默认使用复杂书面语而不是通俗语言。这一层需要用评测集来约束把残障场景视为一等公民纳入模型评估而不是只在发布后由用户反馈。输出层是最容易被忽视的环节也是工程改动成本最低、收益最高的环节。AI 输出的常常是 Markdown、长段落、表格、甚至一整个流式文本流。读屏软件无法理解光标乱跳的流式更新也无法把“#”和“**”读成结构化语义。如果前端直接把模型返回的原始 Markdown 文本塞进直播区域读屏用户听到的很可能是一堆符号噪声。正确的做法是让模型返回结构化 JSON把“短摘要”“详细正文”“不确定性说明”分开前端再把正文渲染成真实的语义 HTML而不是让用户直接接触原始文本。一个比较好的落地模式可以概括为“三个出口”机器可读的 JSON 出口给开发者和其他系统语义化 HTML 出口给读屏软件和正常浏览器纯文本摘要出口给低视力用户或极简界面。也就是说AI 应用的接口设计要从“返回一段字符串”升级为“返回一文一档、多版本可访问内容”。5. 实操示例搭建一个“无障碍优先”的 AI 图片描述服务这里用一个最小可运行的示例演示 AI 输出层的结构化设计。需求场景很常见用户上传一张截图或图片AI 返回三个字段alt_text一句话适合直接作为img的 alt 属性full_description详细描述供读屏用户展开阅读confidence_note对图片中无法确定部分的说明降低误导风险。先准备项目目录和依赖。mkdir a11y-ai-demo cd a11y-ai-demo touch app.py requirements.txt .env.examplerequirements.txt内容如下具体版本以实际项目为准fastapi0.100,1.0 uvicorn[standard]0.23,1.0 openai1.0,2.0 pydantic2.0,3.0.env.example文件用于提示环境变量# 复制为 .env 使用真实密钥绝不能提交到 Git OPENAI_API_KEYyour_api_key_here # 如果你的模型服务提供 OpenAI 兼容接口可在这里指定地址 # OPENAI_BASE_URLhttps://api.example.com/v1然后在app.py中实现服务接口。# 文件路径a11y-ai-demo/app.py import json import os from fastapi import FastAPI, HTTPException from fastapi.middleware.cors import CORSMiddleware from openai import OpenAI from pydantic import BaseModel, Field # OpenAI SDK 会从 OPENAI_API_KEY 环境变量读取密钥 client OpenAI() # 模型名称以你的项目实际使用的视觉模型为准 MODEL os.getenv(VISION_MODEL, gpt-4o-mini) app FastAPI(titlea11y-ai-demo) # 允许本地前端页面跨域请求生产环境应写成明确的域名白名单 app.add_middleware( CORSMiddleware, allow_origins[http://127.0.0.1:3000, http://localhost:3000], allow_methods[POST], allow_headers[Content-Type], ) class ImageQuery(BaseModel): image_url: str Field(description待描述图片的公开 URL 或 base64 data URL) question: str Field(default请描述这张图片的内容, max_length500) class AltTextResult(BaseModel): alt_text: str Field(description一句话替代文本用于 img 的 alt) full_description: str Field(description详细描述适合读屏用户展开阅读) confidence_note: str Field(description对不确定内容的说明避免过度自信) def _build_messages(query: ImageQuery): return [ { role: system, content: ( 你是图片无障碍描述助手。请输出 JSON包含三个字段 alt_text一句话不超过 50 字、 full_description3 到 8 句的详细描述、 confidence_note说明图片里哪些区域无法确定。 不要把 JSON 之外的文字写入回答。 ), }, { role: user, content: [ {type: text, text: query.question}, {type: image_url, image_url: {url: query.image_url}}, ], }, ] def _describe_with_model(query: ImageQuery) - dict: try: response client.chat.completions.create( modelMODEL, messages_build_messages(query), response_format{type: json_object}, temperature0.2, ) content response.choices[0].message.content if not content: raise ValueError(模型返回内容为空) data json.loads(content) return { alt_text: data.get(alt_text, ), full_description: data.get(full_description, ), confidence_note: data.get(confidence_note, ), } except json.JSONDecodeError: raise HTTPException(status_code502, detail模型输出不是合法 JSON请重试) except Exception: # 生产环境应把原始异常记入日志不要把内部细节直接返回给客户端 raise HTTPException(status_code502, detail图片描述服务暂时不可用请稍后重试) app.post(/api/v1/describe-image, response_modelAltTextResult) async def describe_image(query: ImageQuery): if not query.image_url.startswith((http://, https