AWS Lambda Docker镜像sentence-transformers依赖缺失问题求助
我的目标
在AWS Lambda中实现文本转向量功能,将向量存入向量数据库,计划使用sentence-transformers的all-MiniLM-L6-v2模型(若有更简便方案欢迎告知)。注:该库体积过大,无法作为AWS Lambda层使用。
我的需求
将sentence-transformers安装在/tmp目录(AWS Lambda中唯一可写目录),因为即使设置了TRANSFORMERS_CACHE环境变量,该包仍会尝试在packages目录写入文件,导致报错。
遇到的问题
本地运行docker run -p 9000:8080 image:tag测试正常,但部署后出现以下错误:
Runtime.ImportModuleError: Unable to import module 'lambda_function': No module named 'sentence_transformers'
打印sys.path显示/tmp/packages已在路径中:
['/var/task', '/var/runtime', '/var/task', '/tmp/packages', '/var/lang/lib/python311.zip', '/var/lang/lib/python3.11', '/var/lang/lib/python3.11/lib-dynload', '/var/lang/lib/python3.11/site-packages']
相关文件
Dockerfile
FROM public.ecr.aws/lambda/python:3.11 # 获取依赖,以sentence-transformers为例 COPY requirements.txt ${LAMBDA_TASK_ROOT} # 复制Lambda函数代码 COPY lambda_function.py ${LAMBDA_TASK_ROOT} # 将依赖安装到/tmp目录(Lambda唯一可写目录) RUN pip install -r requirements.txt --target=/tmp/packages # 将新的packages目录添加到PYTHONPATH,方便脚本导入 ENV PYTHONPATH "${PYTHONPATH}:/tmp/packages" # 设置Lambda函数入口 CMD [ "lambda_function.handler" ]
lambda_function.py
import sys print(sys.path) import os # 必须在导入SentenceTransformer前修改缓存目录为可写的/tmp os.environ['TRANSFORMERS_CACHE'] = '/tmp/cache/huggingface/models' os.environ['HF_DATASETS_CACHE'] = '/tmp/cache/huggingface/datasets' os.environ['HF_HOME'] = '/tmp/cache/huggingface/home' import json from sentence_transformers import SentenceTransformer model = SentenceTransformer('all-MiniLM-L6-v2') def handler(event, context): return { "statusCode": 200, "body": "res" }
requirements.txt
sentence-transformers
补充疑问
本地查看/tmp/packages有完整依赖,但AWS环境中该目录不存在。请问我遗漏了什么?
核心问题原因
AWS Lambda容器运行时,/tmp是临时挂载的空目录,你在Docker构建阶段安装到/tmp/packages的依赖会被完全覆盖,导致部署后该目录不存在,无法导入模块。
修正步骤
调整依赖安装路径
将依赖安装到Lambda任务目录${LAMBDA_TASK_ROOT},这个目录在运行时会被完整保留,无需额外配置PYTHONPATH(该目录默认就在sys.path中)。修改Dockerfile中的pip命令:RUN pip install -r requirements.txt --target=${LAMBDA_TASK_ROOT}同时删除
ENV PYTHONPATH "${PYTHONPATH}:/tmp/packages"这一行。保留缓存目录配置
你设置的TRANSFORMERS_CACHE等环境变量是正确的,sentence-transformers运行时的模型缓存会写入/tmp,不会触发只读目录写入错误。可选优化:预下载模型减少冷启动时间
为避免Lambda冷启动时下载模型的耗时,可以在构建阶段预下载模型到镜像中:- 在Dockerfile中添加预下载命令:
RUN python -c "from sentence_transformers import SentenceTransformer; model = SentenceTransformer('all-MiniLM-L6-v2'); model.save('/var/task/model')" - 修改lambda_function.py中的模型加载路径:
model = SentenceTransformer('/var/task/model')
- 在Dockerfile中添加预下载命令:
修正后的Dockerfile示例
FROM public.ecr.aws/lambda/python:3.11 COPY requirements.txt ${LAMBDA_TASK_ROOT} COPY lambda_function.py ${LAMBDA_TASK_ROOT} # 安装依赖到任务目录 RUN pip install -r requirements.txt --target=${LAMBDA_TASK_ROOT} # 预下载模型到镜像(可选) RUN python -c "from sentence_transformers import SentenceTransformer; model = SentenceTransformer('all-MiniLM-L6-v2'); model.save('/var/task/model')" CMD [ "lambda_function.handler" ]
替代方案建议
如果镜像体积过大,可考虑:
- 使用AWS Lambda挂载EFS,将依赖和模型存储在EFS中,Lambda运行时挂载读取,避免镜像体积膨胀。
- 使用Hugging Face官方的Transformer推理容器,针对Lambda场景做了优化,适配性更强。
内容的提问来源于stack exchange,提问作者dyesdyes

