1. 项目概述
作为一名在高校信息化建设领域工作多年的技术负责人,我经常遇到学生们提出的各种校园生活问题。从图书馆开放时间到选课流程,这些问题看似简单却占据了大量人工答疑资源。去年指导计算机专业毕业设计时,我和团队萌生了一个想法:能否利用当前热门的Prompt工程技术和轻量化大模型,打造一个专属于校园场景的智能问答系统?
经过三个月的开发和迭代,我们成功构建了一套基于ChatGLM-6B的校园智能问答系统。这个系统最大的特点在于:
- 采用INT4量化技术,使得参数量达60亿的大模型能在普通游戏本上流畅运行
- 通过分场景Prompt模板设计,将校园领域问答准确率提升至88%以上
- 构建了结构化校园知识库,包含教务、图书馆等五大场景的1500余条问答对
- 使用Streamlit实现轻量级前端,支持一键部署和本地演示
提示:系统完整代码已开源,文末附获取方式。特别提醒,所有开发均在合规环境下完成,未使用任何违规技术或工具。
2. 核心技术选型解析
2.1 模型选择:ChatGLM-6B INT4量化版
在模型选型阶段,我们对比了多种开源大模型:
| 模型名称 | 参数量 | 显存占用 | 中文能力 | 量化支持 |
|---|---|---|---|---|
| ChatGLM-6B | 6B | 13GB | 优秀 | 支持 |
| LLaMA-7B | 7B | 14GB | 一般 | 支持 |
| Bloomz-7B | 7B | 15GB | 良好 | 不支持 |
| MOSS-16B | 16B | 32GB | 优秀 | 不支持 |
选择ChatGLM-6B主要基于三点考量:
- 显存优化:INT4量化后显存占用<10GB,GTX1660显卡即可运行
- 中文优势:针对中文场景优化,在校园问答任务上表现优于同等规模模型
- 推理效率:使用相对位置编码,支持长文本生成且推理速度较快
模型加载的核心代码如下:
python复制from transformers import AutoTokenizer, AutoModel
model_path = "./chatglm-6b-int4"
tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)
model = AutoModel.from_pretrained(model_path, trust_remote_code=True).half().cuda()
def generate_response(prompt):
inputs = tokenizer(prompt, return_tensors="pt").to("cuda")
outputs = model.generate(**inputs,
max_length=300,
temperature=0.7,
top_p=0.9)
return tokenizer.decode(outputs[0], skip_special_tokens=True)
2.2 Prompt工程设计方案
2.2.1 基础模板架构
我们设计了分层Prompt结构,包含四个核心要素:
- 角色定义:明确系统身份和职责边界
- 场景约束:限定回答范围仅限校园场景
- 示例演示:提供1-3个典型问答示例
- 格式规范:固定输入输出格式
text复制[角色定义]
你是XX大学智能答疑助手,仅回答与本校相关的校园问题。
[场景约束]
当前问题类别:{scene}
可回答场景:教务管理|图书馆|校园生活|社团活动
[示例演示]
问题:图书馆自习室需要预约吗?
答案:校本部图书馆3-5层自习室需通过"XX大学图书馆"微信公众号预约,每次最长预约4小时。
[用户问题]
{user_question}
[答案生成]
2.2.2 分场景优化技巧
针对不同场景,我们调整了Prompt的以下要素:
- 教务类:强调政策准确性,示例中使用官方文件表述
- 图书馆类:注重细节完整性,包含开放时间、预约方式等
- 生活服务类:提供多解决方案,如"校园卡充值可通过三种方式..."
- 社团类:突出流程指引,分步骤说明参与方式
实测表明,分场景Prompt比通用模板准确率提升12.5%。
3. 知识库构建与检索
3.1 数据结构设计
采用JSON格式存储知识条目,每个条目包含:
json复制{
"qid": "LIB001",
"question": "图书馆可以带书包进入吗?",
"answer": "读者可携带书包进入图书馆,但贵重物品请自行保管。",
"category": "图书馆",
"keywords": ["入馆", "书包", "携带物品"],
"synonyms": [
"进图书馆要存包吗?",
"带包能进图书馆吗?"
]
}
关键设计点:
- qid采用"场景缩写+序号"的编码方式
- synonyms字段存储问题同义表述,提升匹配率
- keywords用于快速检索,支持空格分隔的多关键词
3.2 混合检索策略
结合传统检索与语义匹配,实现三级检索流程:
- 关键词精确匹配:Jieba分词+TF-IDF权重计算
- 同义词扩展检索:基于知识库synonyms字段
- 语义相似度匹配:使用Sentence-BERT计算问题相似度
python复制from sentence_transformers import SentenceTransformer
encoder = SentenceTransformer('paraphrase-multilingual-MiniLM-L12-v2')
def semantic_search(query, knowledge_base, top_k=3):
queries = [q["question"] for q in knowledge_base]
query_embed = encoder.encode(query)
doc_embed = encoder.encode(queries)
similarities = util.pytorch_cos_sim(query_embed, doc_embed)[0]
top_results = similarities.argsort(descending=True)[:top_k]
return [knowledge_base[i] for i in top_results]
4. 系统实现细节
4.1 整体架构
系统采用分层设计,各模块职责明确:
code复制前端交互层
↑↓
文本预处理层(分词/清洗)
↑↓
知识库检索层(关键词+语义)
↑↓
Prompt生成层(场景适配)
↑↓
模型推理层(ChatGLM-6B)
↑↓
结果后处理层(格式校验)
4.2 核心处理流程
- 问题接收:通过Streamlit界面获取用户输入
- 场景识别:基于关键词匹配确定问题类别
- 知识检索:从本地JSON知识库查找最佳匹配
- Prompt组装:动态生成包含场景信息的Prompt
- 模型推理:调用ChatGLM-6B生成回答
- 结果验证:检查回答是否包含拒答关键词(如"不知道")
python复制def process_question(user_input):
# 场景分类
scene = classify_scene(user_input)
# 知识检索
kb_results = search_knowledge(user_input)
# Prompt生成
prompt = build_prompt(
user_input,
scene=scene,
examples=kb_results[:2]
)
# 模型推理
raw_answer = generate_response(prompt)
# 结果校验
if contains_rejection(raw_answer):
return fallback_response(kb_results)
return postprocess(raw_answer)
5. 部署与优化
5.1 轻量级部署方案
使用PyInstaller打包为单文件可执行程序:
bash复制pyinstaller --onefile --add-data "knowledge_base.json;." app.py
部署环境要求:
- Windows 10/11或Ubuntu 18.04+
- NVIDIA显卡(GTX1660及以上)
- 16GB内存
- 20GB可用磁盘空间
5.2 性能优化技巧
-
模型加载加速:
python复制model = AutoModel.from_pretrained(model_path, trust_remote_code=True, device_map='auto', torch_dtype=torch.float16) -
缓存机制:
- 对高频问题建立LRU缓存
- 缓存最近10次对话历史
-
流式输出:
python复制for response, history in model.stream_chat(tokenizer, query, history=history): print(response, end="", flush=True)
6. 实测效果分析
在200条测试集上的评估结果:
| 场景 | 准确率 | 平均响应时间 | 拒答率 |
|---|---|---|---|
| 教务管理 | 91.2% | 2.3s | 4.5% |
| 图书馆服务 | 93.7% | 1.8s | 2.1% |
| 校园生活 | 86.4% | 2.7s | 7.3% |
| 社团活动 | 82.5% | 3.1s | 10.2% |
| 综合表现 | 88.4% | 2.5s | 6.0% |
典型问题处理示例:
用户问:选修课挂了怎么办?
系统答:根据《XX大学学籍管理规定》,选修课不及格可采取以下措施:
- 在下一学期开学两周内申请补考
- 重新选修该课程或其他同类课程
- 用其他课程学分替代(需教务审批)
具体流程请登录教务系统→"考试报名"→"补考申请"查看。
7. 常见问题解决
7.1 模型回答偏离预期
解决方案:
- 强化Prompt中的约束条件
- 调整temperature参数(建议0.5-0.7)
- 添加后处理过滤器:
python复制def validate_answer(answer): blacklist = ["不确定", "不清楚", "无法回答"] return not any(word in answer for word in blacklist)
7.2 显存不足问题
应对措施:
- 使用--pre_layer参数控制加载层数
bash复制
python app.py --pre_layer 20 - 启用CPU卸载:
python复制model = AutoModel.from_pretrained(model_path, device_map="balanced", offload_folder="./offload")
7.3 知识库更新机制
实现动态加载:
python复制def reload_knowledge():
global knowledge_base
with open('knowledge_base.json', 'r', encoding='utf-8') as f:
knowledge_base = json.load(f)['data']
8. 项目扩展方向
-
多模态支持:
- 解析上传的校园通知图片
- 处理语音输入问题
-
智能推荐:
- 根据历史问答推荐相关问题
- 主动推送重要通知(如考试安排变更)
-
联邦学习:
- 各校区部署边缘节点
- 定期聚合更新核心模型
这个项目的完整代码和数据集已整理在GitHub仓库(地址见文末),包含详细的使用文档和测试案例。在实际部署到我校信息服务中心后,系统日均处理咨询量达到300+次,显著减轻了人工客服压力。
