三大实战项目搭建

📚 Day8:RAG 知识库项目搭建(Vue3+FastAPI)

目标:跑通「上传 PDF → 解析 → 向量检索 → 问答」的完整流程

一、后端(FastAPI)极简代码

1. 安装依赖

bash

运行

复制代码
pip install fastapi uvicorn pdfplumber faiss-cpu sentence-transformers python-multipart

2. 核心代码 main.py

python

运行

复制代码
from fastapi import FastAPI, UploadFile, File
from fastapi.responses import JSONResponse
import pdfplumber
import faiss
import numpy as np
from sentence_transformers import SentenceTransformer

app = FastAPI()

# 初始化模型和向量库
model = SentenceTransformer("all-MiniLM-L6-v2")
index = faiss.IndexFlatL2(384)  # 384维向量
text_chunks = []

# 1. 上传并解析PDF
@app.post("/upload")
async def upload_pdf(file: UploadFile = File(...)):
    with pdfplumber.open(file.file) as pdf:
        text = "\n".join([page.extract_text() for page in pdf.pages])
    
    # 分块(每块500字)
    chunks = [text[i:i+500] for i in range(0, len(text), 500)]
    embeddings = model.encode(chunks)
    
    # 存入向量库
    index.add(np.array(embeddings))
    text_chunks.extend(chunks)
    return {"status": "success", "chunks_count": len(chunks)}

# 2. 问答接口
@app.post("/chat")
async def chat(question: str):
    # 问题向量化+检索
    q_emb = model.encode([question])
    _, indices = index.search(np.array(q_emb), k=2)
    context = "\n".join([text_chunks[i] for i in indices[0]])
    
    # 拼接prompt(简化版)
    answer = f"根据文档:{context[:200]}... 回答:{question}的相关信息是XXX"
    return {"answer": answer}

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)

3. 启动服务

bash

运行

复制代码
python main.py

访问 http://localhost:8000/docs 就能直接测试接口。


二、前端(Vue3+TS)极简代码

1. 安装依赖

bash

运行

复制代码
npm create vite@latest rag-front -- --template vue-ts
cd rag-front
npm install axios element-plus

2. 核心页面 src/App.vue

vue

复制代码
<template>
  <el-container>
    <el-upload action="/api/upload" :before-upload="beforeUpload" :on-success="handleUploadSuccess">
      <el-button>上传PDF文档</el-button>
    </el-upload>

    <el-input v-model="question" placeholder="输入你的问题" style="margin-top:20px" />
    <el-button @click="handleChat" style="margin-top:10px">提问</el-button>

    <div class="answer-box" style="margin-top:20px">{{ answer }}</div>
  </el-container>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import axios from 'axios'

const question = ref('')
const answer = ref('')

const beforeUpload = (file: File) => {
  if (file.type !== 'application/pdf') {
    alert('仅支持PDF文件')
    return false
  }
  return true
}

const handleUploadSuccess = () => {
  alert('上传成功,可开始提问!')
}

const handleChat = async () => {
  const res = await axios.post('http://localhost:8000/chat', { question: question.value })
  answer.value = res.data.answer
}
</script>

3. 配置跨域 vite.config.ts

ts

复制代码
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
  plugins: [vue()],
  server: {
    proxy: {
      '/api': {
        target: 'http://localhost:8000',
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, '')
      }
    }
  }
})

4. 启动前端

bash

运行

复制代码
npm run dev

打开 http://localhost:5173,上传 PDF、提问,就能看到 RAG 效果!


📚 Day9:Agent 办公助手项目搭建

目标:实现「工具调用」能力,让 AI 能 "调用计算器 / 查天气"

一、后端工具调用逻辑(扩展 Day8 的 main.py

python

运行

复制代码
import json

# 定义工具
tools = [
    {
        "name": "calculator",
        "description": "用于计算数学表达式",
        "parameters": {"expression": "str,如'2+3*4'"}
    }
]

# 工具执行函数
def call_tool(name, params):
    if name == "calculator":
        return {"result": eval(params["expression"])}
    return {"error": "工具不存在"}

# 修改chat接口,增加工具调用逻辑
@app.post("/agent_chat")
async def agent_chat(question: str):
    # 简化版:判断是否需要调用计算器
    if any(c in question for c in ["+", "-", "*", "/", "等于多少"]):
        # 模拟模型决定调用工具
        tool_call = {"name": "calculator", "parameters": {"expression": "".join([c for c in question if c in "0123456789+-*/"])}}
        tool_result = call_tool(tool_call["name"], tool_call["parameters"])
        answer = f"计算结果:{tool_result['result']}"
    else:
        answer = "这是普通问答结果"
    return {"answer": answer}

二、前端扩展对话历史

修改 App.vue,增加对话列表:

vue

复制代码
<template>
  <div class="chat-container">
    <div v-for="msg in messages" :key="msg.id" :class="msg.role">
      {{ msg.content }}
    </div>
    <el-input v-model="question" @keyup.enter="handleAgentChat" />
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import axios from 'axios'

const messages = ref([])
const question = ref('')

const handleAgentChat = async () => {
  messages.value.push({ role: 'user', content: question.value })
  const res = await axios.post('/api/agent_chat', { question: question.value })
  messages.value.push({ role: 'assistant', content: res.data.answer })
  question.value = ''
}
</script>

<style scoped>
.user { text-align: right; background: #e6f7ff; padding: 8px; margin: 8px 0; }
.assistant { text-align: left; background: #f0f0f0; padding: 8px; margin: 8px 0; }
</style>

📚 Day10:多模态文档问答项目搭建

目标:支持图片 + 扫描 PDF 解析,实现图文问答

一、后端增加 OCR 能力

1. 安装依赖

bash

运行

复制代码
pip install paddlepaddle paddleocr pdf2image

2. 增加图片解析接口

python

运行

复制代码
from PIL import Image
from paddleocr import PaddleOCR

ocr = PaddleOCR(use_angle_cls=True, lang='ch')

@app.post("/upload_image")
async def upload_image(file: UploadFile = File(...)):
    image = Image.open(file.file)
    result = ocr.ocr(image, cls=True)
    text = "\n".join([line[1][0] for line in result[0]])
    
    # 存入向量库(和文本一样分块+向量化)
    chunks = [text[i:i+500] for i in range(0, len(text), 500)]
    embeddings = model.encode(chunks)
    index.add(np.array(embeddings))
    text_chunks.extend(chunks)
    return {"status": "success", "ocr_text": text[:100]}

二、前端增加图片上传

修改 App.vue 的上传组件:

vue

复制代码
<el-upload
  action="/api/upload_image"
  accept="image/*"
  :on-success="handleUploadSuccess"
>
  <el-button>上传图片</el-button>
</el-upload>

📚 Day11:流式对话(SSE/WebSocket)实现

目标:实现 AI 回答逐字输出,解决等待卡顿问题

一、后端 SSE 接口

python

运行

复制代码
from fastapi.responses import StreamingResponse
import asyncio

@app.get("/stream_chat")
async def stream_chat(question: str):
    async def event_generator():
        answer = "根据文档查询结果,我来为你解答:"
        for char in answer:
            yield f"data: {char}\n\n"
            await asyncio.sleep(0.05)  # 控制输出速度
    return StreamingResponse(event_generator(), media_type="text/event-stream")

二、前端 SSE 对接

vue

复制代码
<script setup lang="ts">
const connectSSE = (question: string) => {
  const source = new EventSource(`/api/stream_chat?question=${encodeURIComponent(question)}`)
  source.onmessage = (event) => {
    // 逐字追加到当前回答
    messages.value[messages.value.length - 1].content += event.data
  }
}
</script>

✅ 验收标准

按步骤做完,你将拥有一个完整的 AI 应用 Demo:

  1. 支持 PDF / 图片上传解析
  2. 支持 RAG 知识库问答
  3. 支持 Agent 工具调用
  4. 支持流式对话输出
  5. 基于 Vue3+TS 开发,可直接写进简历

相关推荐
武子康2 小时前
Build-Your-Own-X 从零构建轻量级事件驱动微框架:嵌入式与物联网场景下的极简实践
人工智能·后端·物联网·ai·c#·大模型·嵌入式
aicat_cn14 小时前
LLM Agent记忆最新综述!三阶段演进框架+两大前沿机制总结
ai·大模型
格桑阿sir18 小时前
09-大模型智能体开发工程师:结构化输出与JSON Schema
ai·大模型·llm·agent·json schema·智能体·结构化
relis21 小时前
AI使用小技巧: 用zed和MinerU本地版,同时学习PDF文档的文字和图片
ai·pdf·大模型·agent
自律懒人1 天前
AI Agent 记忆方案横评:Memoria vs OpenClaw vs MCP,让Agent记住你的3种方式
人工智能·大模型·ai编程
bryant_meng1 天前
【SAMv1】 The “Segment Anything” Revolution in Computer Vision
人工智能·深度学习·计算机视觉·大模型·sam·分割一切
Komorebi_99991 天前
Day2:模型部署、接口封装、服务化、容器基础
大模型
格桑阿sir1 天前
14-大模型智能体开发工程师:ReAct推理-行动框架
ai·大模型·llm·agent·react·智能体·推理模型
weixin_468466851 天前
通义千问核心能力与实战表现深度评测
人工智能·深度学习·算法·ai·大模型