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 启动时遇到的问题

问题: 首次启动特别慢,要等好几分钟 解决: 这是正常的,模型第一次加载需要时间。加载完成后会缓存起来,后续启动就快了。可以在下班时间或周末做首次部署。

问题: 提示显存不足 解决: 可以尝试以下方法:

  1. 减少 max_new_tokens 参数值
  2. 使用CPU模式运行(去掉GPU相关配置)
  3. 分批部署,先给部分部门试用

问题: 回答内容不相关或质量不高 解决: 调整系统提示词,让AI更清楚自己的角色:

system_prompt = """你是[公司名称]的内部智能助手,专门帮助员工解决工作相关问题。
你的回答应该专业、准确、有帮助。
如果不知道答案,就说不知道,不要编造信息。
请用中文回答,保持友好和专业的语气。"""

7.2 日常运维问题

问题: 多人同时使用时响应变慢 解决: 可以考虑:

  1. 升级服务器硬件
  2. 设置对话队列,避免同时处理太多请求
  3. 分时段使用,避开高峰时间

问题: 员工问了一些不合适的问题 解决: 在系统提示词中加入限制:

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星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐