AI 数学辅导老师项目构想和初始化

项目产生原因

拍照搜题是个非常有用的操作,尤其对于学生学习辅助帮助很大,市面上这类的软件也有很多,但能不能结合 AI 做出核心功能,并且可以商用? 而不是技术的自嗨模式,真的有用户使用上,先能产生公益价值。

项目初始化

结构

lua 复制代码
ai-math-tutor/
  frontend/
  backend/

后端初始化

1)进入 backend 目录:

bash 复制代码
mkdir ai-math-tutor
cd ai-math-tutor
mkdir backend
cd backend
python3 -m venv venv

激活虚拟环境:

macOS / Linux

bash 复制代码
source venv/bin/activate

2)安装依赖

复制代码
pip install fastapi uvicorn python-dotenv openai

3)创建目录结构

bash 复制代码
backend/
  app/
    main.py
    schemas.py
    llm_service.py
  .env
  requirements.txt

llm_service.py

ini 复制代码
import os
import json
from openai import OpenAI
from dotenv import load_dotenv

load_dotenv()

client = OpenAI(
    api_key=os.getenv("OPENAI_API_KEY"),
    base_url=os.getenv("OPENAI_BASE_URL"),
)

MODEL = os.getenv("OPENAI_MODEL", "moonshot-v1-8k")


SYSTEM_PROMPT = """
你是一位专业的初中数学辅导老师,擅长:
1. 一元一次方程
2. 二元一次方程
3. 几何基础
4. 分数与整数运算
5. 一次函数

请严格返回 JSON:
{
  "answer": "最终答案",
  "steps": ["步骤1", "步骤2"],
  "knowledge_points": ["知识点1"],
  "similar_question": "类似题"
}

要求:
1. 只返回 JSON
2. 每个步骤必须适合学生理解
3. 不要省略关键推导
4. 如果题目超出初中范围,也要说明
"""

def solve_math_question(question: str):
    resp = client.chat.completions.create(
        model=MODEL,
        temperature=0.3,
        messages=[
            {"role": "system", "content": SYSTEM_PROMPT},
            {"role": "user", "content": f"题目:{question}"},
        ],
    )

    content = resp.choices[0].message.content.strip()

    try:
        data = json.loads(content)
        return data
    except Exception:
        return {
            "answer": "解析失败",
            "steps": [content],
            "knowledge_points": ["待识别"],
            "similar_question": "请再输入一道类似题目",
        }

main.py

python 复制代码
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from app.schemas import SolveQuestionRequest, SolveQuestionResponse
from app.llm_service import solve_math_question

app = FastAPI(title="AI Math Tutor API")

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)


@app.get("/")
def health():
    return {"message": "AI Math Tutor API is running"}


@app.post("/api/solve", response_model=SolveQuestionResponse)
def solve_question(req: SolveQuestionRequest):
    result = solve_math_question(req.question)
    return SolveQuestionResponse(**result)

schemas.py

python 复制代码
from pydantic import BaseModel
from typing import List


class SolveQuestionRequest(BaseModel):
    question: str


class SolveQuestionResponse(BaseModel):
    answer: str
    steps: List[str]
    knowledge_points: List[str]
    similar_question: str

4)写 .env

如果你用 Moonshot/OpenAI 兼容接口,可以这样:

ini 复制代码
OPENAI_API_KEY=你的key
OPENAI_BASE_URL=https://api.moonshot.cn/v1
OPENAI_MODEL=moonshot-v1-8k

如果是 OpenAI 官方兼容接口,就改成对应地址。

启动

backend 目录下执行:

lua 复制代码
uvicorn app.main:app --reload --port 8000

打开:

arduino 复制代码
http://127.0.0.1:8000/docs

你可以直接在 Swagger 页面测试接口。

前端初始化

1)创建前端项目

回到项目根目录:

sql 复制代码
cd ..
npm create vite@latest frontend

选择:

  • Vue
  • JavaScript 或 TypeScript 都行

建议你用 TypeScript。

进入目录:

bash 复制代码
cd frontend
npm install
npm install axios naive-ui

2)前端目录建议

css 复制代码
frontend/
  src/
    api/
      math.ts
    views/
      Home.vue
    App.vue
    main.ts

3)写 src/api/math.ts

typescript 复制代码
import axios from 'axios'

const request = axios.create({
  baseURL: 'http://127.0.0.1:8000',
  timeout: 30000,
})

export interface SolveRequest {
  question: string
}

export interface SolveResponse {
  answer: string
  steps: string[]
  knowledge_points: string[]
  similar_question: string
}

export function solveMathQuestion(data: SolveRequest) {
  return request.post<SolveResponse>('/api/solve', data)
}

4)写 src/main.ts

javascript 复制代码
import { createApp } from 'vue'
import App from './App.vue'

createApp(App).mount('#app')

5)写 src/App.vue

xml 复制代码
<template>
  <div class="page">
    <div class="container">
      <h1>AI 数学辅导老师</h1>

      <textarea
        v-model="question"
        class="question-input"
        placeholder="请输入一道数学题,例如:解方程 3x + 5 = 11"
      />

      <button class="submit-btn" @click="handleSubmit" :disabled="loading">
        {{ loading ? '解析中...' : '开始解析' }}
      </button>

      <div v-if="result" class="result-card">
        <h2>答案</h2>
        <p>{{ result.answer }}</p>

        <h2>步骤解析</h2>
        <ol>
          <li v-for="(item, index) in result.steps" :key="index">
            {{ item }}
          </li>
        </ol>

        <h2>知识点</h2>
        <ul>
          <li v-for="(item, index) in result.knowledge_points" :key="index">
            {{ item }}
          </li>
        </ul>

        <h2>相似题</h2>
        <p>{{ result.similar_question }}</p>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { solveMathQuestion, type SolveResponse } from './api/math'

const question = ref('')
const loading = ref(false)
const result = ref<SolveResponse | null>(null)

const handleSubmit = async () => {
  if (!question.value.trim()) return

  loading.value = true
  try {
    const { data } = await solveMathQuestion({
      question: question.value,
    })
    result.value = data
  } catch (error) {
    console.error(error)
    alert('解析失败,请检查后端是否启动')
  } finally {
    loading.value = false
  }
}
</script>

<style scoped>
.page {
  min-height: 100vh;
  background: #f5f7fa;
  padding: 40px 16px;
}
.container {
  max-width: 800px;
  margin: 0 auto;
  background: #fff;
  padding: 24px;
  border-radius: 12px;
}
.question-input {
  width: 100%;
  min-height: 140px;
  padding: 12px;
  border: 1px solid #ddd;
  border-radius: 8px;
  resize: vertical;
  font-size: 16px;
  box-sizing: border-box;
}
.submit-btn {
  margin-top: 16px;
  padding: 10px 18px;
  border: none;
  background: #18a058;
  color: #fff;
  border-radius: 8px;
  cursor: pointer;
}
.result-card {
  margin-top: 24px;
  padding: 20px;
  background: #fafafa;
  border-radius: 8px;
}
</style>

6)启动前端

arduino 复制代码
npm run dev

运行结果

nice !

相关推荐
HelloReader2 小时前
从零创建你的第一个 Flutter 应用(一)
前端
程序员阿峰2 小时前
别再写JS监听滚动了!一行CSS搞定导航固定+通讯录效果(附3个案例)
前端
用户0332126663672 小时前
将 PDF 文档转换为图片【Python 教程】
python
wordbaby2 小时前
前端进阶:小程序 Canvas 2D 终极指北 — 给图片优雅添加水印
前端·canvas
树上有只程序猿2 小时前
OpenClaw虽香,但不是人人都养得起“小龙虾
前端·openai
七牛云行业应用2 小时前
保姆级 OpenClaw 避坑指南:手把手教你看日志修 Bug,顺畅连通各大 AI 模型
人工智能·后端·node.js
程序员爱钓鱼2 小时前
Go并发控制核心:context 包完整技术解析
后端·google·go
树獭叔叔2 小时前
OpenClaw Plugins 与 Hooks 系统:让 AI 助手无限可能
后端·aigc·openai
SuperEugene2 小时前
Vue3 + Element Plus 全局 Message、Notification 封装与规范|Vue生态精选
前端·javascript·vue.js