课程目标

  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. 简述:为什么前后端联调时会出现跨域问题?如何解决?
  4. 作业 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. 跨域原因 浏览器出于安全同源策略限制:网页只能请求同协议、同域名、同端口的资源。当前端页面地址 和 后端接口地址 协议 / 域名 / 端口任意一项不同,浏览器就会拦截请求,触发跨域报错。

  9. 解决办法(本课程方案) 在 FastAPI 后端引入 CORSMiddleware 跨域中间件,配置允许访问的源、请求方法、请求头,后端主动声明允许跨域访问,浏览器就会放行请求。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐