WACATW commited on
Commit
d7cfbb9
·
verified ·
1 Parent(s): 9808601

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +62 -83
app.py CHANGED
@@ -1,83 +1,62 @@
1
- import os
2
- os.environ.setdefault("SYSTEM", "spaces")
3
-
4
- # ===== Monkey Patch: 修复 gradio_client 的 bool-schema Bug =====
5
- import gradio_client.utils as _gcu
6
-
7
- if hasattr(_gcu, "_json_schema_to_python_type"):
8
- _orig = _gcu._json_schema_to_python_type
9
- def _safe(schema, defs=None):
10
- if isinstance(schema, bool):
11
- return "Any"
12
- return _orig(schema, defs)
13
- _gcu._json_schema_to_python_type = _safe
14
-
15
- if hasattr(_gcu, "get_type"):
16
- _orig_get_type = _gcu.get_type
17
- def _safe_get_type(schema):
18
- if not isinstance(schema, dict):
19
- return "Any"
20
- return _orig_get_type(schema)
21
- _gcu.get_type = _safe_get_type
22
- # ===== Monkey Patch 结束 =====
23
-
24
- import gradio as gr
25
- import torch
26
- from transformers import AutoModelForCausalLM, AutoTokenizer
27
- from PIL import Image
28
-
29
- # ============================================================
30
- # 模型初始化
31
- # ============================================================
32
- model_id = "vikhyatk/moondream2"
33
- revision = "2024-08-26"
34
-
35
- print("正在加载 Moondream2 模型...")
36
- tokenizer = AutoTokenizer.from_pretrained(model_id, revision=revision)
37
- model = AutoModelForCausalLM.from_pretrained(
38
- model_id,
39
- trust_remote_code=True,
40
- revision=revision,
41
- torch_dtype=torch.float32,
42
- low_cpu_mem_usage=True,
43
- )
44
- print("模型加载完成。")
45
-
46
- # ============================================================
47
- # 推理函数
48
- # ============================================================
49
- def answer_question(image: Image.Image, question: str):
50
- if image is None:
51
- return "⚠️ 请先上传一张作业图片。"
52
- if not question or not question.strip():
53
- return "⚠️ 请输入你的问题。"
54
-
55
- enc_image = model.encode_image(image)
56
- answer = model.answer_question(enc_image, question, tokenizer)
57
- return answer
58
-
59
- # ============================================================
60
- # Gradio 界面
61
- # ============================================================
62
- demo = gr.Interface(
63
- fn=answer_question,
64
- inputs=[
65
- gr.Image(type="pil", label="📷 上传作业图片"),
66
- gr.Textbox(
67
- label="💬 你的问题",
68
- placeholder="例如:这道题的答案是多少?请逐步解答。",
69
- lines=2,
70
- ),
71
- ],
72
- outputs=gr.Textbox(label="🤖 AI 回答", lines=8),
73
- title="📚 作业识图 AI (CPU 版)",
74
- description="上传作业照片,输入问题,AI 会尝试识别并给出答案。",
75
- theme=gr.themes.Soft(),
76
- )
77
-
78
- if __name__ == "__main__":
79
- demo.launch(
80
- server_name="0.0.0.0",
81
- server_port=7860,
82
- share=True,
83
- )
 
1
+ from fastapi import FastAPI, UploadFile, File, Form, Depends, HTTPException
2
+ from fastapi.staticfiles import StaticFiles
3
+ from fastapi.responses import FileResponse
4
+ import auth, storage, ai_search
5
+
6
+ app = FastAPI(title="云学习平台")
7
+ app.mount("/static", StaticFiles(directory="static"), name="static")
8
+
9
+ @app.on_event("startup")
10
+ def startup():
11
+ auth.init_db()
12
+ storage.ensure_bucket()
13
+
14
+ # ── 用户认证 ──
15
+ @app.post("/auth/register")
16
+ def register(username: str = Form(...), password: str = Form(...)):
17
+ conn = auth.sqlite3.connect(auth.DB_PATH)
18
+ try:
19
+ conn.execute(
20
+ "INSERT INTO users (username, password_hash, created_at) VALUES (?,?,?)",
21
+ (username, auth.hash_password(password), auth.datetime.now().isoformat())
22
+ )
23
+ conn.commit()
24
+ except auth.sqlite3.IntegrityError:
25
+ raise HTTPException(400, "用户名已存在")
26
+ finally:
27
+ conn.close()
28
+ token = auth.create_access_token({"sub": username})
29
+ return {"access_token": token, "token_type": "bearer"}
30
+
31
+ @app.post("/auth/login")
32
+ def login(username: str = Form(...), password: str = Form(...)):
33
+ conn = auth.sqlite3.connect(auth.DB_PATH)
34
+ row = conn.execute("SELECT password_hash FROM users WHERE username=?", (username,)).fetchone()
35
+ conn.close()
36
+ if not row or not auth.verify_password(password, row[0]):
37
+ raise HTTPException(401, "用户名或密码错误")
38
+ token = auth.create_access_token({"sub": username})
39
+ return {"access_token": token, "token_type": "bearer"}
40
+
41
+ # ── 文件上传 ──
42
+ @app.post("/files/upload")
43
+ async def upload(file: UploadFile = File(...), user: str = Depends(auth.get_current_user)):
44
+ content = await file.read()
45
+ path = storage.upload_file(content, file.filename, user, file.content_type or "application/octet-stream")
46
+ return {"path": path, "filename": file.filename}
47
+
48
+ @app.get("/files/list")
49
+ def list_files(user: str = Depends(auth.get_current_user)):
50
+ return {"files": storage.list_user_files(user)}
51
+
52
+ # ── AI 识图搜索 ──
53
+ @app.post("/ai/search-by-image")
54
+ async def search_by_image(file: UploadFile = File(...), user: str = Depends(auth.get_current_user)):
55
+ image_bytes = await file.read()
56
+ description = await ai_search.analyze_image(image_bytes)
57
+ results = await ai_search.search_in_library(description, user, storage)
58
+ return {"ai_description": description, "results": results}
59
+
60
+ @app.get("/")
61
+ def root():
62
+ return FileResponse("static/index.html")