From e59296fb468e2855a2f43dde02f06d16307821ee Mon Sep 17 00:00:00 2001
From: fruge365 <1656639338@qq.com>
Date: Tue, 23 Dec 2025 21:24:14 +0800
Subject: [PATCH 1/2] =?UTF-8?q?=E7=AC=AC=E4=B8=80=E6=AC=A1=E6=8F=90?=
=?UTF-8?q?=E4=BA=A4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.gitignore | 26 ++
README.md | 80 ++---
app.py | 5 +
config.py | 19 ++
core/agents.py | 49 +++
core/prompts.py | 32 ++
requirements.txt | 2 +
server.py | 58 ++++
templates/analytics.html | 113 +++++++
templates/base.html | 79 +++++
templates/index.html | 254 +++++++++++++++
templates/knowledge.html | 89 ++++++
templates/mistakes.html | 116 +++++++
ui/components.py | 69 +++++
ui/interface.py | 109 +++++++
ui/styles.py | 293 ++++++++++++++++++
...00\346\234\257\346\226\207\346\241\243.md" | 74 +++++
17 files changed, 1412 insertions(+), 55 deletions(-)
create mode 100644 .gitignore
create mode 100644 app.py
create mode 100644 config.py
create mode 100644 core/agents.py
create mode 100644 core/prompts.py
create mode 100644 requirements.txt
create mode 100644 server.py
create mode 100644 templates/analytics.html
create mode 100644 templates/base.html
create mode 100644 templates/index.html
create mode 100644 templates/knowledge.html
create mode 100644 templates/mistakes.html
create mode 100644 ui/components.py
create mode 100644 ui/interface.py
create mode 100644 ui/styles.py
create mode 100644 "\346\212\200\346\234\257\346\226\207\346\241\243.md"
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..81b49c1
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,26 @@
+# Python
+__pycache__/
+*.py[cod]
+*$py.class
+
+# Virtual Environment
+.venv/
+venv/
+env/
+
+# Environment Variables / Secrets
+env.sh
+.env
+
+# OS
+.DS_Store
+
+# IDEs
+.idea/
+.vscode/
+
+# Project specific
+.temp/
+
+# Gradio
+flagged/
diff --git a/README.md b/README.md
index 6446d62..7459ec9 100644
--- a/README.md
+++ b/README.md
@@ -1,55 +1,25 @@
-# 造浪2025AIAgent创新赛
-
-#### 介绍
-在数字化转型与行业智能化升级浪潮下,企业业务流程复杂度攀升,用户需求多元化。AI Agent 凭借自动化、智能化特征,可优化流程、提升效率、降低出错率,满足更多业务场景的多元化需求,提升服务质量与用户体验,革新我们的工作和生活方式。
-对此,开源中国 携手 独家冠名厂商-商汤大装置 聚焦多业务场景,携手知名技术专家、合作社区推出“造浪 2025 AI Agent 创新赛”,聚焦智慧金融、教育科技、出海辅助、本地生活等多个重点行业领域,面向企业开发者、高校科研团队及个人创客征集具备商业价值与社会效益的 AI Agent 应用。
-
-
-
-#### 我们希望看到
-- 通过 Agent 实现的创造性解决方案和产出
-- 能显著提升工作效率的 Agent 工作流
-- 探索 Agent 能力边界的实验性项目
-- 能为公众带来实际价值的 Agent 应用
-
-#### 大赛亮点
-本次 AI Agent 创新赛官方指定开发框架 LazyLLM ,由商汤 LazyAGI 团队开发,具备一键部署所有模块的能力,简化了多 Agent 应用的部署流程,可依次启动各个子模块(如 LLM 、Embedding 等)服务并配置 URL 的问题,使整个过程更加顺畅高效。
-
-- 跨平台兼容:无需修改代码,即可一键切换操作系统和IaaS平台,目前兼容裸金属服务器、开发机、Slurm集群、公有云等。这使得开发中的应用可以无缝迁移到其他IaaS平台,大大减少了代码修改的工作量。
-- 统一的使用体验:统一了不同服务商的线上模型和本地部署模型的使用体验,使得开发者可以随意的切换和升级自己的模型进行尝试。此外,还统一了主流的推理框架、微调框架、关系型数据库、向量数据库、文档数据库的使用体验。
-- 高效的模型微调:支持对应用中的模型进行微调,持续提升应用效果。根据微调场景,自动选择最佳的微调框架和模型切分策略。这不仅简化了模型迭代的维护工作,还让算法研究员能够将更多精力集中在算法和数据迭代上,而无需处理繁琐的工程化任务。
-
-#### 赛题设计
-
-1. 智慧金融
-- 开发一款能分析合同审核的智能Agent
-- 开发一款具备风险预警的多模态Agent
-
-2. 教育科技
-- 开发一款教案/长篇技术文档生成Agent
-- 开发一款多模态作业批改的教培Agent
-
-3. 出海辅助
-- 开发一款跨境电商选品的Agent
-- 开发一款收录各大独立站的资讯Agent
-
-#### 参赛规则
-
-一、作品要求:
-- 需提交完整的作品方案介绍文档、项目源代码。
-- 参赛者提交的参赛作品必须为原创作品,不得侵犯任何第三方的著作权、商标权及其他知识产权,且不得违反国家相关法律法规,否则将取消其本届大赛的参赛资格;
-- 参赛作品应能正常运行并可达到参赛赛项规定的预期结果。参赛作品应与设计文档描述的功能一致。如参赛作品未能实现设计文档中描述的所有功能,应注明未实现功能、占比及其重要程度。
-- 参赛作品的代码注释应清晰、简洁、准确地描述其设计思路、功能和原理等,以提升代码的可读性和可维护性。
-
-二、LazyLLM 相关链接
-- 官方文档:https://docs.lazyllm.ai/zh-cn/latest/
-- 下载链接:https://github.com/LazyAGI/LazyLLM
-
-三、作品提交
-- 作品需要使用商汤 LazyAGI 团队开发到 LazyLLM 开源低代码大模型应用开发工具进行开发,该工具提供从应用搭建、数据准备、模型部署、微调到评测的一站式工具支持,以极低的成本快速构建 AI 应用——
-- 作品提交内容包含:Agent 系统本体、技术文档(项目简介、成员贡献清单、技术栈、架构设计、部署说明)可选:操作录屏视频(≤5min,可以发布在网盘设置公开可见)
-
-#### 组委会联系方式
-刘老师 :liuyang3@oschina.cn 王老师 :wanghao@oschina.cn
-
-* 大赛解释权归大会组委会所有
+# 智启学伴 (Smart Learning Companion)
+
+## 简介
+“智启学伴”是一款专为 K12 及终身学习者打造的智能化 AI 教育助手,基于 LazyLLM 框架开发。它突破了传统在线教育的单向灌输模式,采用 Multi-Agent(多智能体)架构,集成了“定制规划”、“学科答疑”、“知识复盘”和“情感陪伴”四大核心能力。
+
+系统能够像真人私教一样,精准识别学生的薄弱知识点,自动生成个性化的学习路径;在答疑过程中,它不仅给出答案,更通过苏格拉底式提问引导学生独立思考;同时,其内置的错题本和学习分析仪表盘,能实时反馈学习进度,帮助用户科学高效地提升学业表现,真正实现“因材施教”的教育愿景。
+
+## 快速开始
+
+### 1. 配置 API Key
+```bash
+# 编辑 env.sh
+export LAZYLLM_GLM_API_KEY="your_key"
+```
+
+### 2. 启动应用
+```bash
+# 安装依赖
+pip install -r requirements.txt
+
+# 启动
+python3 app.py
+```
+
+更多详情请查阅 [技术文档.md](技术文档.md)。
diff --git a/app.py b/app.py
new file mode 100644
index 0000000..04e5c2a
--- /dev/null
+++ b/app.py
@@ -0,0 +1,5 @@
+from ui.interface import MainInterface
+
+if __name__ == "__main__":
+ app = MainInterface()
+ app.launch()
diff --git a/config.py b/config.py
new file mode 100644
index 0000000..a515aa4
--- /dev/null
+++ b/config.py
@@ -0,0 +1,19 @@
+import os
+
+class Config:
+ @staticmethod
+ def load_keys():
+ if os.path.exists('env.sh'):
+ with open('env.sh', 'r') as f:
+ for line in f:
+ if line.startswith('export '):
+ k, v = line.replace('export ', '').strip().split('=', 1)
+ os.environ[k] = v.strip('"\'')
+
+ @staticmethod
+ def get_llm_source():
+ if os.environ.get('LAZYLLM_GLM_API_KEY'):
+ return 'glm'
+ elif os.environ.get('LAZYLLM_DOUBAO_API_KEY'):
+ return 'doubao'
+ return 'openai'
diff --git a/core/agents.py b/core/agents.py
new file mode 100644
index 0000000..6815618
--- /dev/null
+++ b/core/agents.py
@@ -0,0 +1,49 @@
+import lazyllm
+from lazyllm.tools import IntentClassifier
+from lazyllm.components import AlpacaPrompter
+from core.prompts import (
+ SYSTEM_PROMPT_PLAN,
+ SYSTEM_PROMPT_TUTOR,
+ SYSTEM_PROMPT_REVIEW,
+ SYSTEM_PROMPT_CHAT
+)
+from config import Config
+
+class AgentSystem:
+ def __init__(self):
+ Config.load_keys()
+ self.source = Config.get_llm_source()
+ print(f"Using LLM Source: {self.source}")
+
+ self.base_llm = lazyllm.OnlineChatModule(source=self.source)
+ self.classifier = self._build_classifier()
+
+ def _build_classifier(self):
+ # Create Specialized Agents
+ plan_agent = self.base_llm.share(
+ prompt=AlpacaPrompter(dict(system=SYSTEM_PROMPT_PLAN, user="{input}"))
+ )
+ tutor_agent = self.base_llm.share(
+ prompt=AlpacaPrompter(dict(system=SYSTEM_PROMPT_TUTOR, user="{input}"))
+ )
+ review_agent = self.base_llm.share(
+ prompt=AlpacaPrompter(dict(system=SYSTEM_PROMPT_REVIEW, user="{input}"))
+ )
+ chat_agent = self.base_llm.share(
+ prompt=AlpacaPrompter(dict(system=SYSTEM_PROMPT_CHAT, user="{input}"))
+ )
+
+ # Initialize Intent Classifier
+ ic = IntentClassifier(self.base_llm)
+ with ic:
+ ic.case['定制学习方案', plan_agent]
+ ic.case['学科答疑', tutor_agent]
+ ic.case['知识复盘', review_agent]
+ ic.case['闲聊', chat_agent]
+ return ic
+
+ def chat(self, message):
+ try:
+ return self.classifier(message)
+ except Exception as e:
+ return f"System Error: {str(e)}"
diff --git a/core/prompts.py b/core/prompts.py
new file mode 100644
index 0000000..8246409
--- /dev/null
+++ b/core/prompts.py
@@ -0,0 +1,32 @@
+SYSTEM_PROMPT_PLAN = """
+你是一位专业的个性化教育顾问。你的核心任务是“因材施教”。
+请根据用户的描述(特别是知识薄弱点),为他们生成一份详细的定制化学习方案。
+方案应包括:
+1. 现状分析
+2. 学习目标
+3. 详细的学习计划(分阶段)
+4. 推荐的资源或练习
+请保持语气鼓励且专业。
+"""
+
+SYSTEM_PROMPT_TUTOR = """
+你是一位博学的学科辅导老师。你的任务是“答疑解惑”。
+请准确、清晰地回答学生提出的学科问题。
+对于复杂问题,请分步骤讲解。如果涉及公式或代码,请规范展示。
+鼓励学生多思考,而不仅仅是给出答案。
+"""
+
+SYSTEM_PROMPT_REVIEW = """
+你是一位负责任的复习考察老师。你的任务是“知识复盘”。
+不要直接讲解知识,而是通过模拟师生对话的方式,向用户提问,检查他们对某个知识点的掌握情况。
+采用苏格拉底式教学法,引导学生自己发现错误或完善答案。
+"""
+
+SYSTEM_PROMPT_CHAT = """
+你是“智启学伴”AI Agent,一款聚焦个性化教育的智能助手。
+你可以:
+1. 为用户制定学习方案(请告诉我你的薄弱项)
+2. 解答学科难题
+3. 进行知识点复盘和模拟考试
+请热情地引导用户使用上述功能。
+"""
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..34f31ca
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,2 @@
+lazyllm
+gradio
diff --git a/server.py b/server.py
new file mode 100644
index 0000000..01cc2ea
--- /dev/null
+++ b/server.py
@@ -0,0 +1,58 @@
+from fastapi import FastAPI, Request
+from fastapi.staticfiles import StaticFiles
+from fastapi.templating import Jinja2Templates
+from fastapi.responses import JSONResponse
+from pydantic import BaseModel
+import uvicorn
+import os
+from core.agents import AgentSystem
+
+# Initialize FastAPI
+app = FastAPI()
+
+# Mount static files
+app.mount("/static", StaticFiles(directory="static"), name="static")
+
+# Templates
+templates = Jinja2Templates(directory="templates")
+
+# Initialize Agent System
+agent_system = AgentSystem()
+
+class ChatRequest(BaseModel):
+ message: str
+ history: list = []
+
+@app.get("/")
+async def read_root(request: Request):
+ return templates.TemplateResponse("index.html", {"request": request, "active_tab": "chat"})
+
+@app.get("/knowledge")
+async def read_knowledge(request: Request):
+ return templates.TemplateResponse("knowledge.html", {"request": request, "active_tab": "knowledge"})
+
+@app.get("/analytics")
+async def read_analytics(request: Request):
+ return templates.TemplateResponse("analytics.html", {"request": request, "active_tab": "analytics"})
+
+@app.get("/mistakes")
+async def read_mistakes(request: Request):
+ return templates.TemplateResponse("mistakes.html", {"request": request, "active_tab": "mistakes"})
+
+@app.post("/api/chat")
+async def chat_endpoint(request: ChatRequest):
+ try:
+ # Here we just pass the message to the agent system
+ # The agent system currently returns a string
+ response_text = agent_system.chat(request.message)
+ return JSONResponse(content={"response": response_text})
+ except Exception as e:
+ return JSONResponse(content={"error": str(e)}, status_code=500)
+
+def start_server():
+ print("🚀 启动智启学伴 Web 服务...")
+ print("👉 访问地址: http://127.0.0.1:8000")
+ uvicorn.run(app, host="0.0.0.0", port=8000)
+
+if __name__ == "__main__":
+ start_server()
diff --git a/templates/analytics.html b/templates/analytics.html
new file mode 100644
index 0000000..1b7931e
--- /dev/null
+++ b/templates/analytics.html
@@ -0,0 +1,113 @@
+{% extends "base.html" %}
+
+{% block content %}
+
+
+
+{% endblock %}
diff --git a/templates/base.html b/templates/base.html
new file mode 100644
index 0000000..8d3f128
--- /dev/null
+++ b/templates/base.html
@@ -0,0 +1,79 @@
+
+
+
+
+
+ 智启学伴 - 您的专属 AI 学习助手
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {% block content %}{% endblock %}
+
+
+
+
diff --git a/templates/index.html b/templates/index.html
new file mode 100644
index 0000000..e77e44b
--- /dev/null
+++ b/templates/index.html
@@ -0,0 +1,254 @@
+{% extends "base.html" %}
+
+{% block content %}
+
+
+ 智启学伴
+
+
+
+
+
+
+
+
+
+
+ AI 生成内容仅供参考,请以教材为准
+
+
+
+
+
+
+{% endblock %}
diff --git a/templates/knowledge.html b/templates/knowledge.html
new file mode 100644
index 0000000..b7c6071
--- /dev/null
+++ b/templates/knowledge.html
@@ -0,0 +1,89 @@
+{% extends "base.html" %}
+
+{% block content %}
+
+
+
+
+
我的知识库
+
管理您的学习资料、笔记和视频课程
+
+
+
+
+
+
+
+ 🔍
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
高中数学必修一重点公式汇总
+
包含集合、函数概念、基本初等函数等核心考点。
+
+ 2.4 MB
+ 2023-10-24
+
+
+
+
+
+
+
牛顿运动定律详解(名师课)
+
深入浅出讲解牛顿三大定律及其应用场景。
+
+ 45 min
+ 2023-11-02
+
+
+
+
+
+
+
英语定语从句错题整理
+
个人整理的易错题集,包含详细解析。
+
+ 12 Items
+ 2023-11-15
+
+
+
+
+
+
+
化学反应原理思维导图
+
涵盖热化学、电化学、化学平衡等章节。
+
+ Image
+ 2023-12-01
+
+
+
+
+{% endblock %}
diff --git a/templates/mistakes.html b/templates/mistakes.html
new file mode 100644
index 0000000..604053a
--- /dev/null
+++ b/templates/mistakes.html
@@ -0,0 +1,116 @@
+{% extends "base.html" %}
+
+{% block content %}
+
+
+
+
+
智能错题本
+
自动归纳错题,针对性强化训练
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 数学 · 函数
+
+ 2023-11-20
+
+
+ 已知函数 f(x) = ln(x^2 + 1) + ax,若 f(x) 在区间 (0, 1) 上单调递增,求实数 a 的取值范围。
+
+
+
+
+
+ 你的答案
+ a ≥ -1
+
+
+ 正确答案
+ a ≥ 0
+
+
+
+
+
+
+
+
+
+
+
+
+
解析:
+
求导得 f'(x) = 2x/(x^2+1) + a。由 f(x) 在 (0, 1) 单调递增,知 f'(x) ≥ 0 在 (0, 1) 恒成立。
+
即 a ≥ -2x/(x^2+1) 在 (0, 1) 恒成立。令 g(x) = -2x/(x^2+1),利用基本不等式或求导可知 g(x) 在 (0, 1) 上的最小值为 -1 (当 x=1 时取到,但区间开),或者直接分析范围。
+
注意:本题易错点在于分离参数后的不等式处理。
+
+
+
+
+
+
+
+ 物理 · 力学
+
+ 2023-11-18
+
+
+ 一物体在水平面上做匀速直线运动,受到水平拉力 F 的作用。若拉力 F 突然增大为 2F,则物体的加速度大小为?(设摩擦力不变)
+
+
+
+
+
+ 你的答案
+ F/m
+
+
+ 正确答案
+ F/m (需要考虑摩擦力 f = F)
+
+
+
+
+
+
+
+
+
+
+
+
+
解析:
+
物体原先做匀速直线运动,说明 F = f(摩擦力)。
+
当拉力变为 2F 时,合力 F_net = 2F - f = 2F - F = F。
+
根据牛顿第二定律,a = F_net / m = F/m。
+
+
+
+
+{% endblock %}
diff --git a/ui/components.py b/ui/components.py
new file mode 100644
index 0000000..bffa446
--- /dev/null
+++ b/ui/components.py
@@ -0,0 +1,69 @@
+# Components for the Doubao-like UI
+
+SIDEBAR_HTML = """
+
+"""
+
+WELCOME_HTML = """
+
+
🎓
+
你好,同学!今天想攻克什么难题?
+
我是你的专属 AI 学习助手。无论是制定计划、解答难题,还是知识复盘,我都能帮你轻松搞定。
+
+
+
+"""
diff --git a/ui/interface.py b/ui/interface.py
new file mode 100644
index 0000000..a26f979
--- /dev/null
+++ b/ui/interface.py
@@ -0,0 +1,109 @@
+import gradio as gr
+from core.agents import AgentSystem
+from ui.styles import CUSTOM_CSS, PRIMARY_COLOR
+from ui.components import SIDEBAR_HTML, WELCOME_HTML
+
+class MainInterface:
+ def __init__(self):
+ self.system = AgentSystem()
+
+ def respond(self, message, history):
+ if not message:
+ return "", history
+
+ # Add user message immediately
+ history.append((message, None))
+
+ try:
+ response = self.system.chat(message)
+ except Exception as e:
+ response = f"System Error: {str(e)}"
+
+ # Update history with response
+ history[-1] = (message, response)
+ return "", history
+
+ def launch(self):
+ # Using a custom theme object to fine-tune colors
+ theme = gr.themes.Soft(
+ primary_hue="indigo",
+ secondary_hue="gray",
+ neutral_hue="gray",
+ radius_size="lg",
+ ).set(
+ body_background_fill="#F3F4F6",
+ block_background_fill="#FFFFFF",
+ block_border_width="0",
+ shadow_drop="none",
+ button_primary_background_fill=PRIMARY_COLOR,
+ button_primary_text_color="white",
+ )
+
+ with gr.Blocks(css=CUSTOM_CSS, title="智启学伴", theme=theme) as demo:
+ with gr.Row(elem_classes="chat-layout"):
+ # Sidebar (Left)
+ with gr.Column(scale=0, min_width=260, elem_classes="sidebar-column"):
+ gr.HTML(SIDEBAR_HTML)
+
+ # Main Chat Area (Right)
+ with gr.Column(scale=1, elem_classes="chat-main"):
+ # Chatbot area
+ chatbot = gr.Chatbot(
+ elem_id="chatbot",
+ show_label=False,
+ avatar_images=(None, "assets/bot.png"), # User icon handled by CSS
+ bubble_full_width=False,
+ show_copy_button=True,
+ render=False
+ )
+
+ # Welcome Screen (Initially Visible)
+ welcome = gr.HTML(WELCOME_HTML)
+
+ # Chat Container (To handle visibility)
+ with gr.Group(visible=False) as chat_group:
+ chatbot.render()
+
+ # Input Area (Fixed at bottom)
+ with gr.Group(elem_classes="input-area-container"):
+ with gr.Row(elem_classes="input-box-wrapper"):
+ msg = gr.Textbox(
+ show_label=False,
+ placeholder="输入您的问题...",
+ container=False,
+ scale=8,
+ autofocus=True,
+ lines=1,
+ max_lines=5
+ )
+ submit_btn = gr.Button(
+ "➤",
+ variant="primary",
+ size="sm",
+ scale=0,
+ min_width=40,
+ elem_classes="send-btn"
+ )
+
+ # Logic to hide welcome screen on first message
+ def toggle_visibility(history):
+ if len(history) > 0:
+ return gr.update(visible=False), gr.update(visible=True)
+ return gr.update(visible=True), gr.update(visible=False)
+
+ # Event Handlers
+ msg.submit(
+ self.respond, [msg, chatbot], [msg, chatbot]
+ ).then(
+ toggle_visibility, chatbot, [welcome, chat_group]
+ )
+
+ submit_btn.click(
+ self.respond, [msg, chatbot], [msg, chatbot]
+ ).then(
+ toggle_visibility, chatbot, [welcome, chat_group]
+ )
+
+ print("✨ 智启学伴 (DeepSeek/豆包风格) 已就绪!")
+ print("👉 请在浏览器打开: http://127.0.0.1:7860")
+ demo.launch(server_name="0.0.0.0", server_port=7860)
diff --git a/ui/styles.py b/ui/styles.py
new file mode 100644
index 0000000..9a8fa26
--- /dev/null
+++ b/ui/styles.py
@@ -0,0 +1,293 @@
+# Colors - Refined Palette
+PRIMARY_COLOR = "#4F46E5" # Indigo-600
+BG_COLOR = "#FFFFFF" # White background for main area
+SIDEBAR_BG = "#F9FAFB" # Light gray for sidebar
+TEXT_PRIMARY = "#1F2937" # Gray-900
+TEXT_SECONDARY = "#6B7280" # Gray-500
+
+CUSTOM_CSS = """
+@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap');
+
+/* Global Reset */
+body {
+ font-family: 'Inter', -apple-system, system-ui, sans-serif !important;
+ background-color: white !important;
+ margin: 0;
+ padding: 0;
+}
+
+.gradio-container {
+ max-width: 100% !important;
+ padding: 0 !important;
+ margin: 0 !important;
+ height: 100vh !important;
+ background: white !important;
+}
+
+/* --- Sidebar (Left) --- */
+.sidebar-container {
+ background-color: #F9FAFB;
+ height: 100vh;
+ border-right: 1px solid #E5E7EB;
+ padding: 20px 16px;
+ display: flex;
+ flex-direction: column;
+ width: 260px;
+}
+
+.logo-area {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ margin-bottom: 30px;
+ padding: 0 8px;
+}
+
+.logo-icon {
+ font-size: 24px;
+}
+
+.logo-text {
+ font-size: 18px;
+ font-weight: 600;
+ color: #111827;
+}
+
+.nav-item {
+ padding: 10px 12px;
+ border-radius: 8px;
+ margin-bottom: 4px;
+ cursor: pointer;
+ color: #4B5563;
+ font-size: 14px;
+ font-weight: 500;
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ transition: background-color 0.15s;
+}
+
+.nav-item:hover {
+ background-color: #E5E7EB;
+ color: #111827;
+}
+
+.nav-item.active {
+ background-color: #E0E7FF; /* Indigo-100 */
+ color: #4F46E5;
+}
+
+/* --- Main Chat Area (Right) --- */
+.chat-main {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ height: 100vh;
+ background-color: #FFFFFF;
+ position: relative;
+}
+
+/* Chatbot Component Override */
+#chatbot {
+ flex: 1;
+ overflow-y: auto;
+ padding: 0 !important;
+ height: 100% !important;
+ background: transparent !important;
+ box-shadow: none !important;
+ border: none !important;
+}
+
+/* Inner wrapper for messages */
+.wrap {
+ max-width: 800px !important;
+ margin: 0 auto !important;
+ padding: 20px 20px 100px 20px !important; /* Bottom padding for input */
+}
+
+/* Message Styles */
+.message {
+ padding: 0 !important;
+ margin-bottom: 24px !important;
+ background: transparent !important;
+ border: none !important;
+ box-shadow: none !important;
+}
+
+/* User Message */
+.user-message {
+ justify-content: flex-end;
+}
+
+.user-message .message-content {
+ background-color: #F3F4F6 !important; /* Light Gray for User */
+ color: #111827 !important;
+ border-radius: 12px !important;
+ padding: 12px 16px !important;
+ font-size: 15px !important;
+ line-height: 1.6 !important;
+ max-width: 85%;
+ margin-left: auto;
+}
+
+/* Bot Message */
+.bot-message {
+ justify-content: flex-start;
+}
+
+.bot-message .message-content {
+ background-color: transparent !important;
+ color: #111827 !important;
+ padding: 0 !important; /* No bubble look for bot, just text */
+ font-size: 15px !important;
+ line-height: 1.7 !important;
+ width: 100%;
+}
+
+/* Avatar Styling */
+.avatar-container {
+ width: 32px !important;
+ height: 32px !important;
+ margin-right: 12px !important;
+ border-radius: 50% !important;
+ overflow: hidden;
+}
+
+.avatar-image {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+}
+
+/* --- Input Area (Floating Bar) --- */
+.input-area-container {
+ position: absolute;
+ bottom: 30px;
+ left: 50%;
+ transform: translateX(-50%);
+ width: 90%;
+ max-width: 800px;
+ z-index: 100;
+}
+
+.input-box-wrapper {
+ background: #F9FAFB; /* Light gray background like ChatGPT/Claude */
+ border: 1px solid transparent;
+ border-radius: 26px; /* Pill shape */
+ padding: 10px 16px;
+ box-shadow: none; /* Clean look */
+ display: flex;
+ align-items: flex-end;
+ gap: 10px;
+ transition: all 0.2s ease;
+}
+
+.input-box-wrapper:focus-within {
+ background: white;
+ box-shadow: 0 4px 12px rgba(0,0,0,0.08);
+ border-color: #E5E7EB;
+}
+
+/* Textarea Reset */
+.input-box-wrapper textarea {
+ background: transparent !important;
+ border: none !important;
+ box-shadow: none !important;
+ padding: 8px 0 !important;
+ font-size: 16px !important;
+ color: #111827 !important;
+ max-height: 200px;
+ resize: none !important;
+}
+
+.input-box-wrapper textarea::placeholder {
+ color: #9CA3AF !important;
+}
+
+/* Send Button */
+.send-btn {
+ width: 36px !important;
+ height: 36px !important;
+ border-radius: 50% !important;
+ background-color: #E5E7EB !important;
+ color: #9CA3AF !important;
+ border: none !important;
+ display: flex !important;
+ align-items: center !important;
+ justify-content: center !important;
+ padding: 0 !important;
+ margin-bottom: 4px; /* Align with single line text */
+ transition: all 0.2s;
+ box-shadow: none !important;
+}
+
+/* Active Send Button State (Simulated via CSS if text exists - handled by Logic usually, but here we style for hover) */
+.input-box-wrapper:focus-within .send-btn {
+ background-color: #111827 !important; /* Black button when active */
+ color: white !important;
+}
+
+.send-btn:hover {
+ transform: scale(1.05);
+}
+
+/* --- Welcome Screen --- */
+.welcome-container {
+ position: absolute;
+ top: 40%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ text-align: center;
+ width: 100%;
+ max-width: 700px;
+ padding: 0 20px;
+}
+
+.welcome-logo {
+ font-size: 48px;
+ margin-bottom: 16px;
+}
+
+.welcome-title {
+ font-size: 24px;
+ font-weight: 600;
+ color: #111827;
+ margin-bottom: 32px;
+}
+
+.suggestion-grid {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: 12px;
+}
+
+.suggestion-card {
+ background: white;
+ border: 1px solid #E5E7EB;
+ border-radius: 12px;
+ padding: 16px;
+ text-align: left;
+ cursor: pointer;
+ transition: border-color 0.2s;
+}
+
+.suggestion-card:hover {
+ border-color: #D1D5DB;
+ background-color: #F9FAFB;
+}
+
+.suggestion-title {
+ font-size: 14px;
+ font-weight: 600;
+ color: #374151;
+ margin-bottom: 4px;
+}
+
+.suggestion-desc {
+ font-size: 13px;
+ color: #9CA3AF;
+}
+
+/* Gradio Footer Hide */
+footer { display: none !important; }
+"""
diff --git "a/\346\212\200\346\234\257\346\226\207\346\241\243.md" "b/\346\212\200\346\234\257\346\226\207\346\241\243.md"
new file mode 100644
index 0000000..54ceb52
--- /dev/null
+++ "b/\346\212\200\346\234\257\346\226\207\346\241\243.md"
@@ -0,0 +1,74 @@
+# 智启学伴 (Smart Learning Companion)
+
+## 1. 项目简介
+“智启学伴”是一款聚焦个性化教育的 AI Agent 系统,以 “因材施教” 为核心,打通课前预习、课中互动、课后答疑全学习链路。它采用模块化 Multi-Agent 架构,能基于学生的知识薄弱点智能生成定制化学习方案,实时解答学科难题,还能模拟师生对话开展知识点复盘,为 K12 及成人教育用户打造专属智能学习助手。
+
+## 2. 成员贡献清单
+- **核心开发者**: 负责整体架构设计、系统重构、Agent 逻辑实现、Prompt 调优及前端界面开发。
+
+## 3. 技术栈
+- **核心框架**: [LazyLLM](https://github.com/LazyAGI/LazyLLM) (用于构建 Multi-Agent 流程和意图识别)
+- **大模型支持**: 智谱 GLM-4 / 字节 Doubao (通过 LazyLLM 调用)
+- **前端界面**: Gradio (构建现代化交互式 Web UI)
+- **开发语言**: Python 3.10+
+- **架构模式**: 模块化分层架构 (UI/Core/Config 分离)
+
+## 4. 架构设计
+本项目采用 **模块化 Multi-Agent 架构**,代码结构清晰,易于扩展。
+
+### 4.1 目录结构
+```
+SmartTutor/
+├── app.py # 程序入口
+├── config.py # 配置管理
+├── core/ # 核心逻辑层
+│ ├── agents.py # Agent 定义与意图分类器构建
+│ └── prompts.py # 系统提示词管理
+├── ui/ # 界面层
+│ ├── interface.py # Gradio 界面构建
+│ ├── styles.py # 自定义 CSS 样式
+│ └── components.py # HTML 组件 (Sidebar, Header 等)
+└── env.sh # 环境变量配置
+```
+
+### 4.2 核心组件
+1. **Intent Classifier (意图分类器)**:
+ * 位于 `core/agents.py`。
+ * 基于 LazyLLM 的 `IntentClassifier`,实时路由用户请求。
+2. **Specialized Agents (专有智能体)**:
+ * **Planner Agent**: 专注于生成学习计划 (System Prompt defined in `core/prompts.py`)。
+ * **Tutor Agent**: 专注于学科答疑。
+ * **Reviewer Agent**: 专注于知识复盘。
+ * **Chat Agent**: 处理通用闲聊。
+3. **UI Layer (交互层)**:
+ * 位于 `ui/` 目录。
+ * 采用左右分栏布局,左侧为用户画像与学习进度,右侧为对话主窗口。
+ * 集成快捷功能卡片,支持一键触发常用功能。
+
+## 5. 部署说明
+
+### 环境准备
+- 操作系统: macOS / Linux / Windows
+- Python 版本: >= 3.10
+
+### 安装步骤
+
+1. **安装依赖**
+ ```bash
+ pip install -r requirements.txt
+ ```
+
+2. **配置 API Key**
+ 在项目根目录下创建或修改 `env.sh` 文件:
+ ```bash
+ export LAZYLLM_GLM_API_KEY="your_key_here"
+ ```
+
+3. **启动系统**
+ ```bash
+ source env.sh
+ python3 app.py
+ ```
+
+4. **访问应用**
+ 浏览器访问 `http://127.0.0.1:7860`。
--
Gitee
From ca2fefe61091bbbbb6214a98eafec455b39aeae4 Mon Sep 17 00:00:00 2001
From: fruge365 <1656639338@qq.com>
Date: Tue, 23 Dec 2025 22:12:47 +0800
Subject: [PATCH 2/2] =?UTF-8?q?=E6=9B=B4=E6=96=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
README.md | 3 +++
server.py | 16 +++++++++++++--
templates/base.html | 31 ++++++++++++++++++++++++++++-
templates/index.html | 46 +++++++++++++++++++++++++++++++++-----------
4 files changed, 82 insertions(+), 14 deletions(-)
diff --git a/README.md b/README.md
index 7459ec9..86cc3e6 100644
--- a/README.md
+++ b/README.md
@@ -22,4 +22,7 @@ pip install -r requirements.txt
python3 app.py
```
+
+视频地址:【快传】我给你发了 智启学伴.mov, 快来看看 https://www.alipan.com/t/qDRDTETVjwaOBoTI0JyJ 点击链接即可保存。「阿里云盘」APP ,无需下载极速在线查看,视频原画倍速播放。
+
更多详情请查阅 [技术文档.md](技术文档.md)。
diff --git a/server.py b/server.py
index 01cc2ea..f256a2f 100644
--- a/server.py
+++ b/server.py
@@ -42,11 +42,23 @@ async def read_mistakes(request: Request):
@app.post("/api/chat")
async def chat_endpoint(request: ChatRequest):
try:
- # Here we just pass the message to the agent system
- # The agent system currently returns a string
+ # Check if message is empty
+ if not request.message or not request.message.strip():
+ return JSONResponse(content={"error": "Message cannot be empty"}, status_code=400)
+
+ # Call agent system
+ print(f"Received message: {request.message}")
response_text = agent_system.chat(request.message)
+
+ # Handle case where response might be an object or list
+ if not isinstance(response_text, str):
+ response_text = str(response_text)
+
+ print(f"Agent response: {response_text}")
return JSONResponse(content={"response": response_text})
except Exception as e:
+ import traceback
+ traceback.print_exc()
return JSONResponse(content={"error": str(e)}, status_code=500)
def start_server():
diff --git a/templates/base.html b/templates/base.html
index 8d3f128..4c2070d 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -4,10 +4,13 @@
智启学伴 - 您的专属 AI 学习助手
+
-
+
+
+
{% endblock %}
--
Gitee