DeepSeek-R1-Distill-Qwen-1.5B实战案例:将Streamlit界面嵌入内网OA系统流程
DeepSeek-R1-Distill-Qwen-1.5B实战案例:将Streamlit界面嵌入内网OA系统流程
1. 项目背景与价值
很多企业都想在内部办公系统里加个智能助手,方便员工查资料、写报告、解决技术问题。但直接用公网的AI服务,数据安全是个大问题,公司内部的敏感信息谁也不敢往外传。
这个项目就是为了解决这个痛点。我们基于一个叫 DeepSeek-R1-Distill-Qwen-1.5B 的超轻量模型,做了一个完全跑在你本地服务器上的智能对话系统。简单说,就是给你的内网OA系统装个“私有大脑”,所有对话都在公司内部处理,数据不出门,安全又方便。
这个模型特别适合企业用,因为它只有1.5B参数,对硬件要求很低,普通带GPU的服务器就能跑起来,不用买特别贵的专业显卡。它继承了DeepSeek模型强大的逻辑推理能力,又用了Qwen成熟的架构,经过优化后保留了核心的智能水平,但计算开销小了很多。
2. 核心功能亮点
2.1 全本地化部署,数据绝对安全
这是企业最关心的一点。整个系统包括模型文件、对话处理、推理计算,全部都在你的本地服务器上完成。模型文件就放在服务器的 /root/ds_1.5b 目录里,员工的所有提问和AI的回答,数据流完全不出公司网络,跟外网彻底隔离。
想象一下,财务同事问报销政策、研发同事讨论技术方案、人事同事咨询劳动法规,这些涉及公司内部信息的内容,如果传到公网上风险有多大。我们这个方案从根本上解决了数据泄露的担忧。
2.2 开箱即用,操作极其简单
我们用了Streamlit来搭建界面,这是个特别适合快速开发Web应用的工具。做出来的聊天界面跟微信聊天差不多,左边是历史对话,右边是输入框,员工一看就知道怎么用,完全不需要培训。
更省心的是,系统会自动识别你服务器的硬件配置。有GPU就用GPU加速,没有GPU就用CPU慢慢算;能支持哪种计算精度就自动选哪种。你不需要懂什么CUDA、显存分配这些技术细节,装好就能用。
2.3 智能推理,回答有逻辑有过程
这个模型有个很好的特点:它会“边想边说”。比如你问它一个数学题,它不会直接给你答案,而是先展示思考过程:“我们先设未知数为x和y,根据第一个条件列出方程...然后代入第二个条件...最后解得x=3, y=5”。这样你不仅能知道答案,还能理解解题思路。
系统会自动把模型的思考过程整理成清晰的结构,用「思考过程」和「最终回答」分开显示,阅读起来特别舒服。这对于企业培训、知识传递特别有用,员工能看到AI是怎么一步步推导出结论的。
2.4 资源管理智能,长期运行稳定
企业应用最怕用着用着就卡死。我们做了几个优化:
- 对话过程中自动关闭不必要的计算,节省显存
- 侧边栏有个“清空”按钮,一点就能释放内存,开始新对话
- 模型加载一次就缓存起来,后续对话都是秒级响应
- 支持多轮对话,能记住之前的聊天内容,上下文连贯
3. 部署到内网OA系统的完整流程
3.1 环境准备与模型获取
首先要在你的内网服务器上准备好运行环境。这台服务器需要能访问公司的内部网络,通常就是你们放OA系统的那台或者同网段的服务器。
基础环境要求:
- Linux系统(CentOS 7+ 或 Ubuntu 18.04+ 都可以)
- Python 3.8 或更高版本
- 至少8GB内存(如果对话量大建议16GB)
- 有GPU更好(显存4GB以上),没有GPU也能用CPU跑
- 磁盘空间20GB以上(主要放模型文件)
安装步骤:
# 1. 创建项目目录
mkdir -p /opt/company_ai_assistant
cd /opt/company_ai_assistant
# 2. 创建Python虚拟环境(避免污染系统环境)
python3 -m venv venv
source venv/bin/activate
# 3. 安装核心依赖
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118 # 如果有GPU
pip install streamlit transformers accelerate
# 4. 下载模型文件
# 这里需要从你们公司的内部文件服务器获取模型
# 假设模型已经由IT部门准备好,放在内网共享目录
cp /mnt/nas/ai_models/ds_1.5b /root/ds_1.5b -r
3.2 核心代码部署
创建一个 app.py 文件,这就是整个应用的核心:
import streamlit as st
from transformers import AutoTokenizer, AutoModelForCausalLM
import torch
import time
# 设置页面标题和图标
st.set_page_config(
page_title="公司智能助手 - 内网专用",
page_icon="🤖",
layout="wide"
)
# 在侧边栏添加公司Logo和说明
with st.sidebar:
st.image("https://via.placeholder.com/150x50/007bff/ffffff?text=Company+Logo", width=150)
st.title("公司智能助手")
st.markdown("---")
st.markdown("**安全提示:**")
st.markdown("✅ 所有对话数据均在公司内网处理")
st.markdown("✅ 无任何数据上传至外部网络")
st.markdown("✅ 对话记录仅保存在当前会话中")
# 清空对话按钮
if st.button("🧹 清空对话", use_container_width=True):
st.session_state.messages = []
st.rerun()
st.markdown("---")
st.markdown("**使用说明:**")
st.markdown("1. 在下方输入问题")
st.markdown("2. 按回车或点击发送")
st.markdown("3. 查看AI的思考与回答")
# 初始化对话历史
if "messages" not in st.session_state:
st.session_state.messages = []
# 加载模型 - 使用缓存避免重复加载
@st.cache_resource
def load_model():
st.info("🚀 正在加载AI模型,首次加载需要30-60秒...")
model_path = "/root/ds_1.5b"
# 加载分词器
tokenizer = AutoTokenizer.from_pretrained(model_path)
# 加载模型,自动选择设备(GPU/CPU)
model = AutoModelForCausalLM.from_pretrained(
model_path,
device_map="auto",
torch_dtype="auto",
trust_remote_code=True
)
return tokenizer, model
# 显示聊天历史
for message in st.session_state.messages:
with st.chat_message(message["role"]):
st.markdown(message["content"])
# 用户输入
if prompt := st.chat_input("请输入您的问题,例如:如何申请年假?"):
# 添加用户消息到历史
st.session_state.messages.append({"role": "user", "content": prompt})
# 显示用户消息
with st.chat_message("user"):
st.markdown(prompt)
# 显示AI回复(先显示占位符)
with st.chat_message("assistant"):
message_placeholder = st.empty()
# 加载模型(首次调用会加载,后续用缓存)
tokenizer, model = load_model()
# 准备对话格式
messages = [
{"role": "system", "content": "你是一个专业的企业智能助手,帮助员工解决工作相关问题。"},
*st.session_state.messages
]
# 应用聊天模板
text = tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True
)
# 生成回复
inputs = tokenizer(text, return_tensors="pt").to(model.device)
with torch.no_grad(): # 禁用梯度计算,节省显存
outputs = model.generate(
**inputs,
max_new_tokens=1024,
temperature=0.6,
top_p=0.95,
do_sample=True,
pad_token_id=tokenizer.eos_token_id
)
# 解码回复
response = tokenizer.decode(outputs[0][inputs['input_ids'].shape[1]:], skip_special_tokens=True)
# 格式化输出(处理思考链标签)
if "<|think|>" in response and "<|end|>" in response:
think_start = response.find("<|think|>") + len("<|think|>")
think_end = response.find("<|end|>")
think_content = response[think_start:think_end].strip()
answer_content = response[think_end + len("<|end|>"):].strip()
formatted_response = f"""
**🤔 思考过程:**
{think_content}
**📝 最终回答:**
{answer_content}
"""
else:
formatted_response = response
# 逐步显示回复(模拟打字效果)
full_response = ""
for chunk in formatted_response.split():
full_response += chunk + " "
message_placeholder.markdown(full_response + "▌")
time.sleep(0.02)
message_placeholder.markdown(formatted_response)
# 添加AI回复到历史
st.session_state.messages.append({"role": "assistant", "content": formatted_response})
3.3 内网集成配置
现在要把这个应用集成到你们的OA系统里。有两种常见方式:
方式一:iframe嵌入(最简单)
如果你的OA系统支持嵌入网页,直接在OA的某个菜单页面里加入:
<!-- 在OA系统的页面模板中加入 -->
<div class="ai-assistant-section">
<iframe
src="http://内部服务器IP:8501"
width="100%"
height="600px"
frameborder="0"
style="border-radius: 10px;"
>
</iframe>
</div>
方式二:API对接(更灵活)
如果OA系统需要深度集成,可以封装成API服务:
# api_server.py
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import List
import uvicorn
app = FastAPI(title="企业AI助手API")
class ChatRequest(BaseModel):
messages: List[dict]
user_id: str
class ChatResponse(BaseModel):
response: str
thinking_process: str
# 这里复用之前的模型加载和推理代码
# 把generate_response函数单独封装
@app.post("/api/chat")
async def chat_endpoint(request: ChatRequest):
"""
供OA系统调用的聊天接口
"""
try:
# 调用模型生成回复
full_response = generate_response(request.messages)
# 解析思考过程和最终回答
thinking, answer = parse_response(full_response)
return ChatResponse(
response=answer,
thinking_process=thinking
)
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000)
然后在OA系统里调用这个API,把AI回复显示在相应的位置。
3.4 启动与运维脚本
创建启动脚本,方便运维同事管理:
#!/bin/bash
# start_assistant.sh
# 激活虚拟环境
cd /opt/company_ai_assistant
source venv/bin/activate
# 设置环境变量
export STREAMLIT_SERVER_PORT=8501
export STREAMLIT_SERVER_ADDRESS=0.0.0.0
export STREAMLIT_THEME_BASE="light"
# 启动服务(后台运行)
nohup streamlit run app.py --server.port=8501 > assistant.log 2>&1 &
echo "AI助手服务已启动"
echo "访问地址:http://服务器内网IP:8501"
echo "查看日志:tail -f assistant.log"
再创建一个监控脚本:
#!/bin/bash
# check_assistant.sh
# 检查服务是否运行
if pgrep -f "streamlit run app.py" > /dev/null
then
echo "✅ AI助手服务运行正常"
echo "内存使用:"
ps aux | grep streamlit | grep -v grep | awk '{print $4,$5,$6}'
else
echo "❌ AI助手服务未运行"
echo "尝试重启..."
/opt/company_ai_assistant/start_assistant.sh
fi
4. 企业应用场景示例
4.1 人力资源场景
员工自助问答:
- "年假怎么计算?"
- "病假需要什么证明?"
- "公积金提取流程是什么?"
- "绩效考核标准有哪些?"
HR工作辅助:
- 自动生成招聘要求描述
- 整理面试问题清单
- 编写员工培训材料
- 解答劳动法相关问题
4.2 技术研发场景
代码助手:
# 员工提问:写一个Python函数,计算列表中的重复元素
# AI回复:
**🤔 思考过程:**
这个问题需要统计列表中每个元素的出现次数,然后找出出现次数大于1的元素。
可以用字典来记录每个元素的计数,遍历列表,然后筛选出计数大于1的键。
**📝 最终回答:**
```python
def find_duplicates(lst):
"""
找出列表中的重复元素
参数:
lst: 输入列表
返回:
包含所有重复元素的列表
"""
count_dict = {}
duplicates = []
# 统计每个元素的出现次数
for item in lst:
count_dict[item] = count_dict.get(item, 0) + 1
# 找出出现次数大于1的元素
for item, count in count_dict.items():
if count > 1:
duplicates.append(item)
return duplicates
# 使用示例
my_list = [1, 2, 3, 2, 4, 3, 5]
print(find_duplicates(my_list)) # 输出: [2, 3]
4.3 行政办公场景
文档处理:
- "帮我写个会议通知模板"
- "整理这份会议纪要的重点"
- "把这段文字改得更正式一些"
- "检查这份合同的关键条款"
流程咨询:
- "采购申请需要哪些审批?"
- "会议室怎么预定?"
- "出差报销标准是多少?"
- "办公用品申领流程?"
5. 安全与权限管理
5.1 访问控制配置
在内网部署时,可以配置Nginx做访问控制:
# /etc/nginx/sites-available/ai_assistant
server {
listen 8501;
server_name 内部服务器IP;
location / {
# 只允许内网IP段访问
allow 192.168.1.0/24;
allow 10.0.0.0/8;
deny all;
proxy_pass http://127.0.0.1:8501;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# 添加基础认证
auth_basic "Restricted Access";
auth_basic_user_file /etc/nginx/.htpasswd;
}
5.2 对话日志管理
虽然对话内容不存储,但可以记录访问日志用于审计:
# 在app.py中添加日志记录
import logging
from datetime import datetime
logging.basicConfig(
filename=f'/var/log/ai_assistant/access_{datetime.now().strftime("%Y%m")}.log',
level=logging.INFO,
format='%(asctime)s - %(message)s'
)
# 在聊天函数中添加
def log_conversation(user_ip, question_length, response_length):
logging.info(f"IP: {user_ip} - Q: {question_length} chars - R: {response_length} chars")
6. 性能优化建议
6.1 硬件配置建议
根据公司使用规模,可以参考以下配置:
| 员工规模 | 推荐配置 | 预估成本 | 并发能力 |
|---|---|---|---|
| 50人以下 | 4核CPU, 16GB内存, 无GPU | 低 | 支持1-2人同时使用 |
| 50-200人 | 8核CPU, 32GB内存, RTX 3060 12GB | 中 | 支持5-10人同时使用 |
| 200-500人 | 16核CPU, 64GB内存, RTX 4090 24GB | 较高 | 支持20-30人同时使用 |
| 500人以上 | 多服务器负载均衡 | 高 | 支持50+人同时使用 |
6.2 模型响应优化
如果觉得响应速度不够快,可以调整这些参数:
# 在模型生成时调整这些参数
outputs = model.generate(
**inputs,
max_new_tokens=512, # 减少生成长度,加快速度
temperature=0.7, # 稍微提高温度,让回答更多样
top_p=0.9, # 调整采样范围
do_sample=True,
pad_token_id=tokenizer.eos_token_id,
repetition_penalty=1.1, # 避免重复
no_repeat_ngram_size=3 # 避免重复的n-gram
)
7. 常见问题解决
7.1 启动时遇到的问题
问题: 首次启动特别慢,要等好几分钟 解决: 这是正常的,模型第一次加载需要时间。加载完成后会缓存起来,后续启动就快了。可以在下班时间或周末做首次部署。
问题: 提示显存不足 解决: 可以尝试以下方法:
- 减少
max_new_tokens参数值 - 使用CPU模式运行(去掉GPU相关配置)
- 分批部署,先给部分部门试用
问题: 回答内容不相关或质量不高 解决: 调整系统提示词,让AI更清楚自己的角色:
system_prompt = """你是[公司名称]的内部智能助手,专门帮助员工解决工作相关问题。
你的回答应该专业、准确、有帮助。
如果不知道答案,就说不知道,不要编造信息。
请用中文回答,保持友好和专业的语气。"""
7.2 日常运维问题
问题: 多人同时使用时响应变慢 解决: 可以考虑:
- 升级服务器硬件
- 设置对话队列,避免同时处理太多请求
- 分时段使用,避开高峰时间
问题: 员工问了一些不合适的问题 解决: 在系统提示词中加入限制:
system_prompt += """
请注意:不要回答以下类型的问题:
1. 涉及公司机密的信息
2. 攻击性或不当内容
3. 违反法律法规的内容
4. 无法验证的个人建议
"""
8. 总结
把DeepSeek-R1-Distill-Qwen-1.5B模型通过Streamlit嵌入内网OA系统,其实没有想象中那么复杂。整个过程可以总结为四步:
第一步:准备环境 - 在内网服务器上装好Python、相关库,放好模型文件。
第二步:部署应用 - 把我们的代码放上去,配置好启动脚本。
第三步:集成到OA - 用iframe嵌入或者API对接,让员工能在OA里直接使用。
第四步:配置优化 - 根据实际使用情况调整参数,做好权限管理和监控。
这个方案最大的优势就是安全和可控。数据不出内网,完全自主掌控,不用担心隐私泄露。而且成本很低,普通服务器就能跑起来,不需要买昂贵的AI服务许可证。
对于企业来说,这不仅仅是个聊天机器人,更是一个24小时在线的智能工作助手。新员工可以问它公司制度,程序员可以找它查代码,行政人员可以让它写通知,每个人都能用自己熟悉的方式获得帮助。
最重要的是,这个系统会随着使用不断改进。员工问得越多,你就越了解大家需要什么,可以针对性地优化提示词、增加专业知识库,让它越来越懂你的公司、你的业务。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。
更多推荐


所有评论(0)