本实操练习将指导您使用Docker打包一个简单的LangChain应用程序。容器化提供了一致、隔离的环境,使应用程序在不同机器和平台上的部署可预测。这种一致性对生产系统具有实际意义。目标是为基础的LangChain应用程序创建Docker镜像,并在本地作为容器运行它。前提条件开始前,请确保您已安装以下软件:Docker: Docker Desktop(适用于Windows/macOS)或Docker Engine(适用于Linux)。您可以通过在终端运行docker --version来验证安装。Python: 一个可用的Python 3.8+版本。文本编辑器/IDE: 您偏好用于编辑代码文件的工具。步骤 1:创建简单的LangChain应用程序首先,我们来创建一个最小的LangChain应用程序。我们将构建一个简单的链,它接收一个主题并使用LLM生成简短的解释。为您的项目创建一个目录,例如,langchain_docker_app。在此目录中,创建两个文件:app.py和requirements.txt。requirements.txt:langchain>=0.1.0 langchain-openai>=0.1.0 # Or your preferred LLM provider library python-dotenv>=1.0.0 fastapi>=0.100.0 uvicorn>=0.20.0注意:根据您打算使用的LLM,调整LLM提供商库(例如,langchain-google-genai、langchain-anthropic)。app.py:import os from fastapi import FastAPI from langchain_openai import ChatOpenAI from langchain_core.prompts import ChatPromptTemplate from langchain_core.output_parsers import StrOutputParser from langchain_core.runnables import RunnablePassthrough from dotenv import load_dotenv # 加载环境变量(特别是API密钥) load_dotenv() # 确保您的OPENAI_API_KEY已在.env文件或环境中设置 if not os.getenv("OPENAI_API_KEY"): raise ValueError("OPENAI_API_KEY environment variable not set.") # 1. 初始化FastAPI应用 app = FastAPI( title="Simple LangChain API", description="A basic API demonstrating LangChain with Docker.", ) # 2. 设置LangChain组件 prompt_template = ChatPromptTemplate.from_messages( [ ("system", "You are a helpful assistant that explains technical concepts simply."), ("human", "Explain the concept of '{topic}' in one sentence."), ] ) llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0) output_parser = StrOutputParser() # 3. 使用LCEL创建链 chain = ( {"topic": RunnablePassthrough()} # 直接将输入作为'topic'传递 | prompt_template | llm | output_parser ) # 4. 定义API端点 @app.post("/explain") async def explain_topic(data: dict): """ 接受一个带有'topic'键的JSON对象并返回解释。 示例:{"topic": "Docker"} """ topic = data.get("topic") if not topic: return {"error": "Missing 'topic' in request body"}, 400 try: result = chain.invoke(topic) return {"explanation": result} except Exception as e: # 基础错误处理 return {"error": str(e)}, 500 # 添加根端点用于基本检查 @app.get("/") async def read_root(): return {"message": "LangChain API is running."} # 注意:要在本地运行此程序(不先使用Docker) # 您通常会使用:uvicorn app:app --reload --port 8000 # 记住要创建一个包含OPENAI_API_KEY的.env文件在同一目录中创建一个.env文件,以安全地存储您的API密钥:.env:OPENAI_API_KEY=your_openai_api_key_here将your_openai_api_key_here替换为您实际的API密钥。步骤 2:创建DockerfileDockerfile包含Docker构建您的应用程序镜像的指令。在langchain_docker_app目录中创建一个名为Dockerfile(无扩展名)的文件。Dockerfile:# 1. 使用官方Python运行时作为父镜像 # 使用slim版本可减小镜像大小 FROM python:3.11-slim # 2. 设置容器中的工作目录 WORKDIR /app # 3. 将requirements文件复制到容器的/app目录中 # 先复制requirements以借助Docker缓存 COPY requirements.txt . # 4. 安装requirements.txt中指定的任何所需包 # --no-cache-dir 减小层大小 # --upgrade pip 确保我们有最新的pip RUN pip install --no-cache-dir --upgrade pip && \ pip install --no-cache-dir -r requirements.txt # 5. 将其余应用程序代码复制到容器的/app目录中 COPY . . # 6. 使端口8000在此容器外部可用 # 这是Uvicorn将运行的端口 EXPOSE 8000 # 7. 定义环境变量(可选,可被覆盖) # ENV OPENAI_API_KEY=您的默认密钥(如果有) # 最好在运行时传递 # 8. 容器启动时运行app.py # 使用uvicorn运行FastAPI应用程序 # --host 0.0.0.0 使其可从容器外部访问 CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000"]我们来分解这些指令:FROM python:3.11-slim:指定基础镜像。使用slim版本有助于减小最终镜像的大小。WORKDIR /app:设置容器内部的工作目录。后续命令(COPY、RUN、CMD)将相对于此目录执行。COPY requirements.txt .:将requirements文件复制到/app目录。我们首先复制此文件以借助Docker的层缓存。如果requirements.txt未更改,Docker会重复使用安装依赖项的层,从而加速后续构建。RUN pip install ...:安装Python依赖项。--no-cache-dir阻止pip存储下载,从而减小镜像大小。COPY . .:将您项目中的其余文件(如app.py和.env)复制到/app目录中。EXPOSE 8000:通知Docker容器在运行时监听端口8000。这是信息性的;您在运行容器时仍需映射端口。CMD ["uvicorn", ...]:指定容器启动时运行的命令。此处,我们启动Uvicorn服务器来提供FastAPI应用程序,并将其绑定到0.0.0.0,以便可以从容器的网络命名空间外部访问它。步骤 3:构建Docker镜像在您的终端中导航到langchain_docker_app目录。运行以下命令来构建Docker镜像:docker build -t langchain-simple-api:latest .docker build:从Dockerfile构建镜像的命令。-t langchain-simple-api:latest:用名称(langchain-simple-api)和标签(latest)标记镜像。这使得以后引用该镜像更方便。.:指定构建上下文(当前目录),表示Docker应该在哪里查找Dockerfile和应用程序文件。Docker将逐步执行Dockerfile中的指令。您将看到显示每个步骤进度的输出。步骤 4:运行Docker容器镜像成功构建后,您可以将其作为容器运行:docker run -p 8000:8000 --env-file .env --name my-langchain-container langchain-simple-api:latest我们来分析这条命令:docker run:从镜像创建并启动容器的命令。-p 8000:8000:将您主机上的端口8000映射到容器内部的端口8000。这允许您通过机器上的http://localhost:8000访问容器内部运行的FastAPI应用程序。格式为host_port:container_port。--env-file .env:将指定.env文件中的环境变量加载到容器中。这是一种安全的方式来传递API密钥和其他配置,而无需将其硬编码到Dockerfile或镜像中。--name my-langchain-container:为正在运行的容器分配一个名称,以便更方便地管理(例如,停止或查看日志)。langchain-simple-api:latest:指定用于创建容器的镜像。如果您想让容器在后台运行(分离模式),请添加-d标志:docker run -d -p 8000:8000 --env-file .env --name my-langchain-container langchain-simple-api:latest步骤 5:验证应用程序容器运行后,您可以验证应用程序:检查容器日志(特别是在分离模式下运行):docker logs my-langchain-container您应该会看到Uvicorn的输出,表明服务器已启动。访问根端点: 打开您的网络浏览器或使用curl:curl http://localhost:8000/您应该会收到:{"message":"LangChain API is running."}测试/explain端点: 使用curl或Postman等工具发送POST请求:curl -X POST http://localhost:8000/explain \ -H "Content-Type: application/json" \ -d '{"topic": "Kubernetes"}'您应该会收到一个JSON响应,其中包含由LangChain链生成的Kubernetes解释,例如:{"explanation": "Kubernetes is an open-source container orchestration platform that automates the deployment, scaling, and management of containerized applications."}(具体的解释会根据LLM的响应有所不同)。步骤 6:停止并移除容器要停止在前台运行的容器,请在运行它的终端中按Ctrl+C。如果是在分离模式下运行,请使用:docker stop my-langchain-container要移除已停止的容器(可选,释放名称和磁盘空间):docker rm my-langchain-container总结与后续步骤您已成功地将一个使用FastAPI的简单LangChain应用程序打包到Docker容器中并在本地运行。这个过程呈现了容器化的核心工作流程:在Dockerfile中定义环境和依赖项,构建可移植镜像,并可预测地运行它。这个容器化应用程序为部署到之前讨论过的各种环境提供了一个良好的起点,例如虚拟机、Kubernetes集群或无服务器平台。生产工作流程中的下一个合理步骤是将此构建的镜像推送到容器注册表(如Docker Hub、AWS ECR、Google Artifact Registry或Azure Container Registry),您的部署环境可以从那里拉取并运行它。这个练习提供了准备LangChain应用程序部署所需的必要技能。