LangChain Day6 前端视角:简易接口联调思路

课程目标

  1. 学会用 FastAPI 把 LangChain 能力封装成 HTTP 接口
  2. 掌握接口基础写法、请求 / 响应格式
  3. 了解前端调用接口的基本方式,实现前后端联调
  4. 知晓简易部署与跨域基础配置

一、前置准备

1. 安装依赖

bash

运行

复制代码
pip install langchain langchain-openai fastapi uvicorn python-multipart
  • fastapi:高性能接口框架,语法简洁、自动生成接口文档
  • uvicorn:ASGI 服务运行器,用来启动接口服务

2. 基础说明

我们前面写的 LangChain 代码,默认只能本地运行; 封装成接口后,前端、其他服务都能通过网络请求调用 AI 能力,是项目落地的必经步骤。


二、实战 1:基础问答接口(最简示例)

完整后端代码

python

运行

复制代码
# main.py
from fastapi import FastAPI
from langchain_openai import OpenAI
from langchain.chains import LLMChain
from langchain.prompts import PromptTemplate
import os

# 配置密钥
os.environ["OPENAI_API_KEY"] = "你的API_KEY"

# 1. 初始化FastAPI应用
app = FastAPI(title="LangChain 接口服务")

# 2. 初始化LLM与链(复用之前的LangChain逻辑)
llm = OpenAI(temperature=0)
prompt = PromptTemplate(input_variables=["question"], template="请认真回答问题:{question}")
chain = LLMChain(llm=llm, prompt=prompt)

# 3. 定义接口路由:GET 请求
@app.get("/chat")
def chat(question: str):
    """问答接口:传入问题,返回AI回答"""
    answer = chain.run(question)
    return {
        "code": 200,
        "msg": "请求成功",
        "data": {
            "question": question,
            "answer": answer
        }
    }

启动服务

在终端执行命令:

bash

运行

复制代码
uvicorn main:app --reload
  • main:对应代码文件名 main.py
  • app:代码里初始化的 FastAPI 实例
  • --reload:热更新,修改代码无需重启服务(开发专用)

访问 & 测试

服务默认地址:http://127.0.0.1:8000

  1. 自动接口文档:http://127.0.0.1:8000/docs,可视化测试接口
  2. 直接浏览器访问示例: http://127.0.0.1:8000/chat?question=解释一下什么是LangChain

三、实战 2:POST 接口(推荐业务用法)

GET 接口会把参数暴露在地址栏,复杂场景 / 传长文本优先用 POST,格式更规范。

python

运行

复制代码
# main.py 续写/替换
from pydantic import BaseModel

# 定义请求体数据模型(规范入参)
class ChatRequest(BaseModel):
    question: str  # 前端需要传递的字段

# POST 接口
@app.post("/api/chat")
def api_chat(req: ChatRequest):
    answer = chain.run(req.question)
    return {
        "code": 200,
        "question": req.question,
        "answer": answer
    }
  • 依然通过 http://127.0.0.1:8000/docs 进入文档测试,选择 POST 接口填写参数调用。

四、关键问题:跨域(前端必遇)

前端页面(Vue/HTML)直接调用本地接口,会触发跨域请求异常,需要配置跨域中间件。

开启跨域支持(必加代码)

python

运行

复制代码
from fastapi.middleware.cors import CORSMiddleware

# 在 app = FastAPI() 之后添加
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],      # 允许所有域名访问(开发环境用)
    allow_credentials=True,
    allow_methods=["*"],      # 允许所有请求方法
    allow_headers=["*"],      # 允许所有请求头
)

生产环境不要写 ["*"],改为指定前端域名,提升安全性。


五、前端调用示例(原生 HTML,零基础看懂)

写一个简单页面,模拟前端请求后端接口,完成联调:

html

预览

复制代码
<!DOCTYPE html>
<html>
<body>
    <input type="text" id="inputText" placeholder="输入问题">
    <button onclick="sendReq()">提问</button>
    <div id="result"></div>

    <script>
        async function sendReq(){
            const question = document.getElementById("inputText").value;
            // 调用后端POST接口
            const res = await fetch("http://127.0.0.1:8000/api/chat",{
                method: "POST",
                headers:{"Content-Type":"application/json"},
                body: JSON.stringify({question: question})
            })
            const data = await res.json();
            document.getElementById("result").innerText = data.answer;
        }
    </script>
</body>
</html>

运行逻辑:

  1. 保持后端接口服务启动
  2. 直接打开 HTML 文件
  3. 输入内容点击按钮,即可拿到 AI 返回结果

六、拓展:Agent 接口封装(结合上节课内容)

把 Agent 能力也封装成接口,完整串联前后知识点:

python

运行

复制代码
from langchain.agents import AgentExecutor, create_react_agent
from langchain.tools import Calculator, DuckDuckGoSearchRun

# 初始化工具、Agent
tools = [Calculator(), DuckDuckGoSearchRun()]
agent = create_react_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=False)

# Agent 专属接口
@app.post("/api/agent")
def agent_chat(req: ChatRequest):
    res = agent_executor.invoke({"input": req.question})
    return {"answer": res["output"]}

七、核心知识点总结(考点 / 面试重点)

  1. 框架选择:本节课使用 FastAPI 封装接口,轻量易用,适合 AI 服务开发
  2. 请求方式
    • GET:参数拼在 URL,适合简单查询
    • POST:参数放请求体,适合长文本、复杂数据,业务首选
  3. 跨域 :前后端分离项目必须配置 CORSMiddleware,否则前端无法调用
  4. 流程链路 前端页面 → HTTP 请求 → FastAPI 接口 → LangChain 逻辑 → 返回结果给前端

八、课后作业


作业 3:简答题答案

问题:为什么前后端联调时会出现跨域问题?如何解决?

  1. 基于本节课代码,封装一个 RAG 问答接口(复用 Day3 RAG 代码)。
  2. 给接口配置跨域,用原生 HTML 页面调用接口,验证联调成功。
  3. 简述:为什么前后端联调时会出现跨域问题?如何解决?

作业 1:封装 RAG 问答接口(带跨域)

python

运行

复制代码
   from fastapi import FastAPI
   from fastapi.middleware.cors import CORSMiddleware
   from pydantic import BaseModel
   from langchain_openai import OpenAI, OpenAIEmbeddings
   from langchain.vectorstores import FAISS
   from langchain.chains import RetrievalQA
   import os

   # 配置密钥
   os.environ["OPENAI_API_KEY"] = "你的API_KEY"

   # 1. 初始化 FastAPI
   app = FastAPI()

   # 2. 配置跨域(前后端联调必备)
   app.add_middleware(
       CORSMiddleware,
       allow_origins=["*"],
       allow_credentials=True,
       allow_methods=["*"],
       allow_headers=["*"],
   )

   # 3. 构造简易向量库+RAG链路(复用RAG核心逻辑)
   embeddings = OpenAIEmbeddings()
   # 模拟文档数据
   texts = ["LangChain 是一款用于构建大模型应用的开发框架",
            "RAG 检索增强生成,通过检索外部文档提升问答准确性"]
   db = FAISS.from_texts(texts, embeddings)
   retriever = db.as_retriever()

   llm = OpenAI(temperature=0)
   rag_chain = RetrievalQA.from_chain_type(
       llm=llm,
       chain_type="stuff",
       retriever=retriever
   )

   # 4. 定义请求体模型
   class ChatReq(BaseModel):
       question: str

   # 5. RAG 问答接口
   @app.post("/api/rag_chat")
   def rag_chat(req: ChatReq):
       result = rag_chain.run(req.question)
       return {
           "code": 200,
           "question": req.question,
           "answer": result
       }

启动命令:

bash

运行

复制代码
   uvicorn main:app --reload

作业 2:HTML 前端调用页面

html

预览

复制代码
   <!DOCTYPE html>
   <html lang="zh-CN">
   <head>
       <meta charset="UTF-8">
       <title>RAG接口调用</title>
   </head>
   <body>
       <input type="text" id="ques" placeholder="请输入问题" style="width:300px;height:30px;">
       <button onclick="sendRequest()" style="height:30px;">提问</button>
       <div id="res" style="margin-top: 20px; color: #333;"></div>

       <script>
           async function sendRequest(){
               const question = document.getElementById("ques").value;
               const resDom = document.getElementById("res");
               resDom.innerText = "请求中...";

               try {
                   const response = await fetch("http://127.0.0.1:8000/api/rag_chat", {
                       method: "POST",
                       headers: {
                           "Content-Type": "application/json"
                       },
                       body: JSON.stringify({question: question})
                   })
                   const data = await response.json();
                   resDom.innerText = `回答:${data.answer}`;
               } catch (e) {
                   resDom.innerText = "请求失败";
               }
           }
       </script>
   </body>
   </html>

使用步骤:
5. 保持后端服务正常运行
6. 直接打开该 HTML 文件
7. 输入问题点击按钮,即可获取返回结果
8. 跨域原因 浏览器出于安全同源策略 限制:网页只能请求同协议、同域名、同端口的资源。当前端页面地址 和 后端接口地址 协议 / 域名 / 端口任意一项不同,浏览器就会拦截请求,触发跨域报错。

  1. 解决办法(本课程方案) 在 FastAPI 后端引入 CORSMiddleware 跨域中间件,配置允许访问的源、请求方法、请求头,后端主动声明允许跨域访问,浏览器就会放行请求。
相关推荐
叶小鸡12 小时前
Java 篇-项目实战-AI 天机学堂(从 0 到 1)-day4
状态模式
shjsjdmmd13 小时前
Claude API 流式输出(SSE)实战指南:从打字机效果到 Agent 工具调用完整落地
状态模式
前端不太难14 小时前
解码大模型的效率革命:当算力不再是唯一瓶颈
状态模式
前端不太难15 小时前
从算力到存力:AI性能的决定性因素正在重构
人工智能·重构·状态模式
Python私教2 天前
从主题闪烁到 Markdown 阅读体验:RuyiBlog v0.1.1 的前端实现复盘
前端·状态模式
ForgeAI码匠2 天前
后台权限不只是菜单隐藏:Forge Admin 的 RBAC 权限链路拆解
java·spring boot·spring·状态模式
前端不太难2 天前
鸿蒙 PC 为什么需要新的组件体系?
华为·状态模式·harmonyos
c++之路2 天前
状态模式(State Pattern)
ui·状态模式
晓杰'2 天前
从0到1实现Balatro游戏后端(4):玩家手牌操作(出牌 / 弃牌 / 补牌)与状态流转设计
后端·websocket·typescript·node.js·状态模式·项目实战·nestjs