
最近折腾了一套基于AWS的内部AI助手,踩了几个坑,这篇把问题说清楚。
把AI引入企业内部,不是简单接个大模型让人开始提问就完事了。要让内部AI助手真正有用,得让它能访问企业自己的资料,还得有身份验证、权限控制、输入输出安全、完整的日志记录,以及人和AI之间的明确分工。
这个项目我搭了一套基于AWS的内部AI助手,允许已认证员工用企业内部文档作为知识源跟AI助手交互。
整个系统用到的技术栈:
目标不是简单让AI模型生成个回答。
我是要围绕这个模型搭一套完整的应用。
员工登录,通过应用发起请求,API Gateway验证请求,Lambda协调AI工作流,从企业文档中通过托管的Bedrock知识库检索相关信息,模型基于这些上下文生成回答,最后返回给已认证的员工。
系统还设计了一套人工审核流程。AI助手生成初稿和回复供员工审核,不会自动发布内容或代表公司执行操作。
做这个项目最大的收获是把多个AWS服务串起来当成一个系统来用,而不是孤立地学每个服务。
企业内部有很多场景:员工需要反复查文档、看之前的项目、核对公司规范、起草内容,或者找散落在各处的信息。
问题是有资料不等于好找。重要的文档可能散落在不同的文件和文件夹里,历史脚本、文案、提案、品牌规范这些内部资源手动搜索起来非常费劲。
这就是我想用这个项目解决的问题。
思路是搭一个内部AI助手,让员工能更简单地跟企业现有的知识库交互。
不用在开始任务前手动翻一堆文档,员工直接问助手,系统从企业内部知识库检索相关信息。
而且希望回答基于企业自己的资料,而不是完全依赖模型的通用知识。
所以我选了RAG(检索增强生成)架构,配合Amazon Bedrock知识库。
整体流程:内部文档存在S3里,连接到Bedrock知识库。员工提交请求时,应用从知识库检索相关信息,把这些信息作为上下文用于生成回答。
但搭完整系统可不只是一个RAG组件的事。
还得解决认证、API安全、权限、输入输出控制、应用逻辑、日志、基础设施配置这些。
这才是这个项目有意思的地方。
这个助手是给内部员工用的,他们需要处理企业现有的内容和信息。
知识库涵盖了这些领域:
文档在S3里按不同前缀组织:
brand-guidelines/
past-scripts/
captions/
proposals/
比如员工可以让助手基于企业的现有风格和历史作品起草内容。
不是只靠模型的通用知识,而是能检索企业内部相关内容作为上下文。
这样系统就有了两个核心组件:模型提供语言生成能力,企业文档提供上下文,应用把它们串起来。
动手之前,得先想清楚几个实际问题。
助手是内部使用的,得有个机制阻止未认证用户访问应用API。
我用了Amazon Cognito用户池。
浏览器需要跟API通信,但不能让前端直接操作Bedrock或拥有宽泛的AWS权限。
我用了Amazon API Gateway作为API层,配置了JWT授权器,用Cognito颁发的token验证。
基础模型不会自动知道企业的私有文档。
需要一个检索层,能搜索企业内容并把相关信息提供给模型。
这正是Amazon Bedrock知识库发挥作用的地方。
Amazon S3作为文档仓库,也是知识库的数据源。
内部AI助手同样需要对用户提交内容和系统返回内容的控制。
我用了Amazon Bedrock Guardrails。
涉及好几个托管服务,得对每次请求的执行过程有可见性。
Amazon CloudWatch提供后端日志和监控能力。
希望基础设施可复现,而不是完全靠手动在AWS控制台配置。
我用了Terraform来配置和管理AWS资源。
最终架构把员工浏览器和多个AWS托管服务串在一起。
主要请求链路:
员工 → Amplify → Cognito → API Gateway → Lambda → Guardrails → 知识库 → Bedrock模型 → Guardrails → 响应
数据支持链路:
S3 → Bedrock知识库 → 文档处理和索引
CloudWatch提供后端全链路可观测性,IAM控制AWS服务间的访问。
完整的架构图如下:

这个架构的重要之处在于职责分离。浏览器负责界面,Cognito负责认证,API Gateway保护API边界,Lambda协调工作流,Bedrock负责检索和生成,S3存储源文档,CloudWatch提供系统可见性。
我从简单的前端开始。
这个应用不需要大型前端框架,因为界面的主要目的就是让员工简单地进行认证、输入提示词、查看生成的回答。
前端技术栈:
应用包含了助手所需的基本界面。
关键点是前端故意保持简单。
应用的大部分复杂度在后端和AWS服务。
浏览器负责提供用户界面和与API通信。
不应该负责直接访问企业的S3文档、调用Bedrock模型或管理宽泛的AWS权限。
用AWS Amplify托管静态前端。
部署模式很直接。
前端文件部署到Amplify,通过应用的Web界面提供给员工。
这也让我有了展示层和后端的清晰分离。
浏览器跟API通信,API跟后端服务通信,后端跟Bedrock和企业内部知识通信。
截图:内部AI助手前端,通过Amplify部署
接下来是认证问题。
因为是内部应用,得确保只有已认证员工能访问助手。
我用了Amazon Cognito用户池。
Cognito用户池成为应用的身份层。
配置应用让用户通过Cognito的托管登录体验认证。
基本认证流程:
员工 ↓
Amazon Cognito 托管登录 ↓
认证成功 ↓
身份令牌 ↓
前端
前端随后在与后端API通信时使用认证信息。
我希望认证在请求到达应用逻辑之前就完成。
这样Lambda函数就不需要承担"判断请求是否已认证"这种基本职责。
API Gateway可以直接验证Cognito颁发的JWT。
请求链路变成:
浏览器 ↓
Cognito 认证 ↓
JWT ↓
API Gateway ↓
JWT 验证 ↓
Lambda
这样职责分离更清晰。
Cognito处理身份,API Gateway处理API层认证,Lambda处理应用逻辑。
截图:Cognito用户池概览

认证搞定后,需要一个API让前端跟后端通信。
我用了Amazon API Gateway的HTTP API。
应用暴露了一个聊天端点给助手。
这个配置的关键是JWT授权器。
API Gateway路由配置为验证Cognito用户池颁发的token。
这意味着没有有效token的请求不应该到达Lambda函数。
我在实现过程中测试过。
尝试在没有有效认证的情况下访问API,返回:
401 Unauthorized
这是个重要测试,确认了JWT授权器在API层强制执行了认证。
截图:API Gateway路由和JWT授权器

API Gateway验证请求后,请求传给AWS Lambda。
我用Python Lambda函数作为聊天协调器。
Lambda函数成为连接应用和Bedrock服务的核心。
不让前端直接跟Bedrock通信,而是让Lambda函数控制工作流。
概念上,Lambda函数负责:
接收请求 ↓
验证/处理输入 ↓
应用输入Guardrail ↓
检索相关知识 ↓
生成响应 ↓
应用输出Guardrail ↓
返回响应
这是项目里最重要的架构决策之一。
前端不需要知道Bedrock知识库怎么工作,不需要知道模型配置,不需要直接权限调用模型。
只需发送请求到API,Lambda处理协调。
截图:Lambda配置

助手需要访问企业现有信息。
我用了Amazon S3作为文档仓库。
把文档按不同前缀组织:
brand-guidelines/
past-scripts/
captions/
proposals/
这样文档源更容易管理,知识库也有结构化的位置可以检索信息。
重要的一点:S3不是生成答案的组件。
S3存储源文档,Bedrock知识库把这些文档作为数据源。
看RAG工作流时,这个区别就重要了。
截图:S3桶和前缀

这是架构中让助手能处理企业内部知识的部分。
创建了托管的Amazon Bedrock知识库,连接到S3文档源。
文档经过知识库的摄取流程。
整体流程:
S3 文档 ↓
知识库数据源 ↓
摄取 ↓
文档处理 ↓
分块 ↓
嵌入 ↓
向量表示 ↓
检索
员工提问时,系统能从已索引内容中检索相关片段。
模型生成响应时可以用那些检索到的片段作为上下文。
第一次摄取测试没有按预期工作。
问题不在PDF本身。
是S3对象位置和配置的数据源之间的关系有问题。
知识库配置了从某个S3前缀读取,而测试文档不在数据源期望的位置。
修正了S3位置、重新运行摄取后,摄取任务成功完成。
结果显示:
状态: COMPLETE
已扫描: 1
已索引: 1
失败: 0
这是个很有用的调试教训,说明RAG系统可能在模型介入之前就挂了。
如果知识库没有正确摄取文档,模型就没有什么有用的东西可以检索。
截图:知识库配置

接下来是控制AI交互的部分。
用Amazon Bedrock Guardrails添加助手输入输出的控制。
Lambda协调流程变成:
用户提示词 ↓
输入 Guardrail ↓
知识检索 ↓
模型生成 ↓
输出 Guardrail ↓
最终响应
Guardrail配置是项目的重要部分,因为它说明AI模型没有被当成不受限制的组件。
还遇到了Guardrail版本的问题。
改了Guardrail配置后,以为活动版本会反映新配置。
但现有的Guardrail版本是不可变的。
配置变更不会自动修改已创建版本。
测试时,即使已经从Terraform定义里移除了那个配置,地址仍然被检测到。
测试返回:
GUARDRAIL_INTERVENED
并且识别出了地址类别。
这说明Lambda仍然在引用旧版Guardrail。
解决方法是替换Guardrail版本通过Terraform,然后验证Lambda使用的是新版本。
Terraform操作:
terraform apply -replace=aws_bedrock_guardrail_version.creative_assistant
这是项目里很有用的教训之一。
对于有版本的AWS资源,改Terraform配置不一定意味着现有不可变版本会原地变更。
需要理解运行时实际引用的是哪个资源。
截图:Guardrail概览

知识检索层跑通后,Lambda协调器连接到Bedrock基础模型。
Lambda函数需要调用模型的权限。
这引出了测试中的另一个问题。
应用最初成功到达知识检索阶段,但模型生成失败了,因为Lambda执行角色没有模型调用路径所需的bedrock:InvokeModel权限。
这在CloudWatch日志里能看到。
调试过程中有用的一点是,日志显示工作流的早期部分已经正常工作了。
输入Guardrail通过了,知识库返回了结果,失败发生在应用尝试调用模型时。
这就把问题范围缩小到了模型调用和IAM配置,而不是整个应用。
更新了IAM权限后继续测试。
还遇到了模型吞吐量的问题。
基础Claude Sonnet 4.5模型标识符不支持我当时用的按需调用模式。
解决方案是用Claude Sonnet 4.5对应的US推理配置。
然后在Terraform和Lambda环境中更新了模型配置。
这是又一个有用的AWS教训。
在Amazon Bedrock有模型访问权限不意味着每个模型标识符都能用每种调用方式来调用。
模型ID、推理配置和IAM权限都需要和应用调用模型的方式对上。
IAM在整个架构中用于控制各AWS组件能访问什么。
前端不需要权限调用Bedrock。
前端不需要权限读取内部S3文档。
Lambda是需要跟AI工作流所需服务交互的组件。
这就是最小权限原则重要的地方。
不是给应用宽泛的AWS权限,而是围绕系统实际需要的操作创建权限。
Lambda执行角色需要访问相关Bedrock操作和支持资源。
知识库也需要访问其配置数据源所需的权限。
这种分离有助于保持信任边界清晰。
前端 ↓
API Gateway ↓
Lambda ↓
Bedrock 服务
浏览器永远不会收到宽泛的AWS权限来直接操作内部基础设施。
一旦多个AWS服务串在一起,有个清晰的地方检查发生了什么,调试就容易多了。
我用Amazon CloudWatch做Lambda日志和监控。
测试系统时遇到问题时,CloudWatch特别有用。
比如某次请求最初返回:
500
无法生成草稿
单看前端,这个错误提供的信息很有限。
CloudWatch日志提供了实际执行路径。
可以看到:
输入 Guardrail ↓
通过 知识库 ↓
检索到结果 模型调用 ↓
失败
这完全改变了调试过程。
不用猜是Cognito、API Gateway、Lambda、知识库还是模型的问题,可以跟着执行路径定位请求失败的环节。
截图:CloudWatch日志


我用Terraform来配置和管理项目涉及的AWS基础设施。
此时应用已经涉及多个服务:Cognito、API Gateway、Lambda、S3、Bedrock知识库、Bedrock Guardrails、IAM和CloudWatch。全部通过AWS控制台手动创建和配置会让环境难以复现和维护。
我把基础设施定义为代码。
Terraform配置按管理的资源类型拆分成不同文件:
terraform/
├── api-gateway.tf
├── cloudwatch.tf
├── cognito.tf
├── guardrail.tf
├── iam.tf
├── knowledge-base.tf
├── lambda.tf
├── s3.tf
├── variables.tf
└── outputs.tf
这也给调试带来了帮助。
比如发现Claude Sonnet 4.5模型调用需要不同的推理配置和相应IAM配置时,可以在Terraform里修改,然后用:
terraform plan
看Terraform计划在应用前的具体变更内容。
还遇到了Bedrock Guardrail版本的问题。配置已经改了,但现有Guardrail版本不可变,所以只改Terraform配置不会更新Lambda使用的版本。
解决方法是通过Terraform明确替换Guardrail版本:
terraform apply -replace=aws_bedrock_guardrail_version.creative_assistant
这是用Terraform的实际好处之一。基础设施变更,包括调试过程中的变更,都可以追踪和复现,而不是完全靠手动控制台操作。
所以Terraform不是运行时请求链路的一部分。它是用来配置和管理使应用成为可能的所有AWS资源的基础设施层。
各个组件配置好后,我作为完整系统测试应用。
最终工作流:
员工 ↓
AWS Amplify 前端 ↓
Amazon Cognito 认证 ↓
JWT ↓
Amazon API Gateway ↓
JWT 验证 ↓
AWS Lambda ↓
Amazon Bedrock Guardrail ↓
Amazon Bedrock 知识库 ↓
相关内部上下文 ↓
Claude Sonnet 4.5 ↓
输出 Guardrail ↓
Lambda 响应 ↓
API Gateway ↓
前端 ↓
员工
CloudWatch提供后端执行可见性,Terraform提供应用周围的基础设施管理层。
架构的重要之处是每个服务都有特定职责。
前端提供界面,Cognito处理身份,API Gateway保护API边界,Lambda协调工作流,S3存储源文档,Bedrock知识库处理检索,Bedrock提供模型,Guardrails提供AI安全控制,IAM控制权限,CloudWatch提供可观测性,Terraform管理基础设施。
这样我就有了可复现的环境管理方式,而不是完全依赖在AWS控制台手动操作。
这个项目最大的教训是:搭一个AI应用不是简单选个模型就完事了。
模型只是系统的一个组件。
大部分工程工作都围着它转。
认证得能工作,API得拒绝未认证请求,文档得正确摄取,知识库得返回有用的上下文,Lambda执行角色得有正确权限,模型调用方式得跟选定的模型和推理配置匹配,Guardrail版本得正确管理。
出了问题,CloudWatch得能提供足够信息定位失败环节。
这是从云工程角度让项目对我有价值的地方。
我能把多个AWS服务作为一套系统来用,而不是把每个服务当孤立的主题。
最终成果是一个内部AI助手,已认证员工可以跟基于企业自己内容的AI系统交互,同时保持实际内容生成过程由人工审核。
这个项目始于一个相对简单的想法。
让员工用更简单的方式处理企业内已存在的信息。
实现最终涉及了认证、API安全、无服务器计算、对象存储、托管RAG、基础模型、Guardrails、IAM、监控和基础设施即代码。
这才是我觉得最有价值的部分。
AI模型只是应用的一个环节。
真正的工程挑战是围绕它构建一个安全、可观测、可复现、对使用者有用的系统。