网站cn和com哪个做站好/外贸网站设计

网站cn和com哪个做站好,外贸网站设计,怀集网站建设,微网站策划方案从零开始部署DeepSeek:基于OllamaFlask的本地化AI对话系统 一、部署背景与工具选型 在AI大模型遍地开花的2025年,DeepSeek R1凭借其出色的推理能力和开源特性成为开发者首选。本文将以零基础视角,通过以下工具链实现本地化部署: …

从零开始部署DeepSeek:基于Ollama+Flask的本地化AI对话系统


一、部署背景与工具选型

在AI大模型遍地开花的2025年,DeepSeek R1凭借其出色的推理能力和开源特性成为开发者首选。本文将以零基础视角,通过以下工具链实现本地化部署:

1.Ollama:轻量级模型管理工具,支持一键拉取、运行模型

Ollama 是一个功能强大的大语言模型管理端,专为下载、运行和调用大型语言模型(如DeepSeek)而设计。它提供了以下几个核心功能:

  • 模型下载:支持从官方仓库下载不同规模的模型。
  • 模型运行:通过API提供服务,让用户与模型进行交互。
  • 实时对话模拟:以流式方式展示模型回复。
2.DeepSeek : 平衡性能与资源消耗的中等规模模型

DeepSeek 是目标语言模型,可以根据您的硬件配置选择不同的模型规模(如7B、13B等)。它具有以下特点:

  • 可扩展性:根据内存和计算资源调整模型大小。
  • 高效训练:支持并行训练以加速模型收敛。
3.Python+Flask:构建Web交互界面,支持流式响应

Flask 是一个轻量级的Web框架,广泛应用于快速开发Web应用。结合Python,它为构建动态Web界面提供了灵活性:

  • API集成:通过Flask API调用Ollama服务。
  • 前端动态:使用JavaScript和HTML创建交互式对话框。
4.HTML+JavaScript:实现类ChatGPT的对话交互体验

HTML 是构建Web界面的基础语言,用于设计用户友好的对话框,并将其嵌入到Flask应用中。您可以通过以下方式集成:

  • 响应式布局:使用CSS样式表确保界面在不同设备上适配。
  • 动态内容展示:通过JavaScript更新页面内容,模拟模型回复,需要模拟打字机方式。

**备注说明**: 不想自己编程的话,可使用chatbox直接接入ollama

二、环境准备与模型部署

1. 安装Ollama

Windows/Mac用户
访问Ollama官网下载安装包,双击完成安装。 (github下载很慢,需要使用加速或从其他地方下载)

Linux用户

curl -fsSL https://ollama.com/install.sh | sh
sudo systemctl start ollama
2. 下载DeepSeek模型

根据硬件配置选择模型(显存要求参考):

  • 基础版(1.5B):适合笔记本(8GB内存)
  • 标准版(7B):推荐配置(16GB内存+8GB显存)
  • 加强版(70B):需专业显卡(如RTX 5090)
# 拉取7B模型
ollama run deepseek-r1:7b

上述指令会完成下载和运行两个步骤(ollama支持断线续传功能,而且我发现速度慢下来的时候,手动停止然后再启动接着下载模型的话,速度会恢复上来),成功运行后可通过命令行直接向deepseek提问,如下:

另外,也可以在命令行手动执行ollama相关指令:

  • 无参数启动
C:\Users\arbboter\Desktop>ollama
Usage:ollama [flags]ollama [command]Available Commands:serve       Start ollamacreate      Create a model from a Modelfileshow        Show information for a modelrun         Run a modelpull        Pull a model from a registrypush        Push a model to a registrylist        List modelsps          List running modelscp          Copy a modelrm          Remove a modelhelp        Help about any commandFlags:-h, --help      help for ollama-v, --version   Show version informationUse "ollama [command] --help" for more information about a command.
命令功能示例
ollama serve启动模型ollama serve
ollama pull下载模型ollama pull deepseek-r1:7b
ollama list查看本地模型ollama list
ollama rm删除模型ollama rm deepseek-r1:1.5b
ollama cp复制模型ollama cp deepseek-r1:7b my-backup

3.配置ollama

# 限制本地访问(默认配置)
export OLLAMA_HOST=127.0.0.1# 允许局域网访问
export OLLAMA_HOST=0.0.0.0# 启用调试
export OLLAMA_DEBUG=1# 自定义模型路径(可能需重启机器生效)
export OLLAMA_MODELS=~\ollama\models

三、构建Web对话系统

备注说明:选型flask及代码编写基本是由deepseek完成,本人只负责提问和修缮
1. 项目结构
deepseek-web/
├── app.py          # Flask主程序
├── templates/
│   └── index.html  # 聊天界面
2. Flask后端实现(app.py)
# app.py
from flask import Flask, render_template, request, Response
import ollama
import logging
from datetime import datetimeapp = Flask(__name__)# 配置日志
logging.basicConfig(level=logging.INFO,format='%(asctime)s - %(levelname)s - %(message)s',handlers=[logging.FileHandler('chat.log'),logging.StreamHandler()]
)def chat_ollama(user_message, stream):host = 'http://192.168.1.10:11434'cli = ollama.Client(host=host)response = cli.chat(model='deepseek-r1:7b',messages=[{'role': 'user', 'content': user_message}],stream=stream,# options={'temperature': 0.7})return response@app.route('/')
def index():return render_template('index.html')@app.route('/api/chat', methods=['POST'])
def chat():"""流式聊天接口"""def generate(user_message):try:app.logger.info(f"流式处理开始: {user_message[:50]}...")stream = chat_ollama(user_message, True)for chunk in stream:content = chunk['message']['content']if content.startswith('<think>'):content = content.replace('<think>', '', 1)elif content.startswith('</think>'):content = content.replace('</think>', '\n', 1)app.logger.debug(f"发送数据块: {content}")yield f"{content}"app.logger.info("流式处理完成")except Exception as e:app.logger.error(f"流式错误: {str(e)}")yield f"[ERROR] {str(e)}\n\n"return Response(generate(request.json['message']), mimetype='text/event-stream')if __name__ == '__main__':app.run(host='0.0.0.0', port=5001, debug=True)
3. 前端实现(index.html)
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>AI 对话助手</title><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github.min.css"><script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script><style>:root {--primary-color: #10a37f;--bg-color: #f0f2f5;}body {margin: 0;padding: 20px;font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;background-color: var(--bg-color);max-width: 800px;margin: 0 auto;}#chat-container {height: 70vh;overflow-y: auto;border: 1px solid #e0e0e0;border-radius: 8px;padding: 15px;background: white;margin-bottom: 20px;}.message {margin: 12px 0;display: flex;gap: 15px;}.user-message {justify-content: flex-end;}.message-content {max-width: 80%;padding: 12px 16px;border-radius: 8px;}.assistant-message .message-content {background: #f8f9fa;border: 1px solid #e0e0e0;}.user-message .message-content {background: var(--primary-color);color: white;}#input-container {display: flex;gap: 10px;}#user-input {flex: 1;padding: 12px;border: 1px solid #e0e0e0;border-radius: 8px;resize: none;min-height: 44px;}button {background: var(--primary-color);color: white;border: none;padding: 0 20px;border-radius: 8px;cursor: pointer;transition: opacity 0.2s;}button:disabled {opacity: 0.6;cursor: not-allowed;}.typing-indicator {display: inline-block;padding: 8px 12px;background: #f8f9fa;border-radius: 8px;border: 1px solid #e0e0e0;}.dot {display: inline-block;width: 6px;height: 6px;margin-right: 3px;background: #ccc;border-radius: 50%;animation: bounce 1.4s infinite;}@keyframes bounce {0%, 80%, 100% { transform: translateY(0) }40% { transform: translateY(-6px) }}/* markdown基础样式 */.markdown-content {line-height: 1.6;transition: opacity 0.3s;}.markdown-content:not(.markdown-rendered) {opacity: 0.5;}.markdown-content h1 { font-size: 2em; margin: 0.67em 0; }.markdown-content h2 { font-size: 1.5em; margin: 0.83em 0; }.markdown-content pre { background: #f5f5f5;padding: 1em;border-radius: 4px;overflow-x: auto;}</style>
</head>
<body><div id="chat-container"></div><div id="input-container"><textarea id="user-input" placeholder="输入消息..." rows="1"></textarea><button id="send-btn" onclick="sendMessage()">发送</button></div><script>const chatContainer = document.getElementById('chat-container');const userInput = document.getElementById('user-input');const sendBtn = document.getElementById('send-btn');// 滚动到底部function scrollToBottom() {}function renderMarkdown(options = {}) {// 合并配置参数const config = {selector: options.selector || '.markdown-content',breaks: options.breaks ?? true,gfm: options.gfm ?? true,highlight: options.highlight || null};// 配置Markedmarked.setOptions({breaks: config.breaks,gfm: config.gfm,highlight: config.highlight});// 渲染处理器const render = () => {document.querySelectorAll(config.selector).forEach(container => {if (container.dataset.rendered) return;// 创建虚拟容器避免内容闪烁const virtualDiv = document.createElement('div');virtualDiv.style.display = 'none';virtualDiv.innerHTML = container.innerHTML.trim();// 执行Markdown转换container.innerHTML = marked.parse(virtualDiv.innerHTML);container.dataset.rendered = true;// 添加加载动画container.classList.add('markdown-rendered');});};// 自动执行渲染if (document.readyState === 'complete') {render();} else {document.addEventListener('DOMContentLoaded', render);}}// 添加用户消息function addUserMessage(content) {const messageDiv = document.createElement('div');messageDiv.className = 'message user-message';messageDiv.innerHTML = `<div class="message-content">${content}</div>`;chatContainer.appendChild(messageDiv);}// 添加AI消息(流式)async function addAssistantMessageStream() {const messageDiv = document.createElement('div');messageDiv.className = 'message assistant-message';messageDiv.innerHTML = `<div class="message-content markdown-content"><div class="typing-indicator"><span class="dot"></span><span class="dot" style="animation-delay: 0.2s"></span><span class="dot" style="animation-delay: 0.4s"></span></div></div>`;chatContainer.appendChild(messageDiv);return messageDiv.querySelector('.message-content');}// 发送消息async function sendMessage() {const content = userInput.value.trim();if (!content) return;sendBtn.disabled = true;userInput.disabled = true;userInput.value = '';addUserMessage(content);const responseContainer = await addAssistantMessageStream();try {const response = await fetch('/api/chat', {method: 'POST',headers: {'Content-Type': 'application/json',// 如果需要认证// 'Authorization': 'Bearer YOUR_TOKEN'},body: JSON.stringify({ message: content })});if (!response.ok) throw new Error('请求失败');await this.createStreamTypewriter(response, responseContainer, {});this.scrollToBottom();} catch (error) {responseContainer.innerHTML = '❌ 请求出错: ' + error.message;} finally {sendBtn.disabled = false;userInput.disabled = false;userInput.focus();}}// 输入框事件处理userInput.addEventListener('keydown', (e) => {if (e.key === 'Enter' && !e.shiftKey && !e.ctrlKey) {e.preventDefault();sendMessage();} else if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) {userInput.value += '\n';}});async function createStreamTypewriter(stream, container, options = {}) {const config = {baseSpeed: 50,maxSpeedup: 3,retryCount: 3,...options};this.reader = null;// 状态控制let isDestroyed = false;let cursorVisible = true;let renderQueue = [];let retryCounter = 0;// DOM元素初始化const cursor = document.createElement('span');cursor.className = 'typewriter-cursor';cursor.textContent = '▌';container.append(cursor);// 光标动画const cursorInterval = setInterval(() => {cursor.style.opacity = cursorVisible ? 1 : 0;cursorVisible = !cursorVisible;}, 600);// 核心渲染逻辑const renderEngine = () => {if (renderQueue.length === 0 || isDestroyed) return;// 动态调速算法const speed = Math.max(config.baseSpeed / config.maxSpeedup,config.baseSpeed - renderQueue.length * 2);const fragment = document.createDocumentFragment();while (renderQueue.length > 0) {const char = renderQueue.shift();fragment.append(document.createTextNode(char));}container.insertBefore(fragment, cursor);setTimeout(() => requestAnimationFrame(renderEngine), speed);};// 流数据处理const processStream = async () => {try {this.reader = stream.body.getReader();// Fetch模式处理while (!isDestroyed) {const { done, value } = await this.reader.read();if (done) break;renderQueue.push(...new TextDecoder().decode(value).split(''));if (!renderQueue.length) continue;requestAnimationFrame(renderEngine);}} catch (err) {if (retryCounter++ < config.retryCount && !isDestroyed) {processStream();} else {destroy();throw new Error('Stream connection failed');}} finally {container.innerHTML = marked.parse(container.textContent.replace('▌', ''));destroy();}};// 资源清理const destroy = () => {if (isDestroyed) return;isDestroyed = true;clearInterval(cursorInterval);cursor.remove();if (stream.cancel) stream.cancel();if (stream.close) stream.close();};// 启动引擎processStream();return { destroy };};</script>
</body>
</html>

四、启动与优化

1. 运行系统
flask run --port 5001

访问 http://localhost:5001 即可开始对话 ,如下:
主页面

2. 性能优化技巧
  • 量化加速:使用ollama run deepseek-r1:7b --quantize q4_0 减少显存占用
  • GPU加速:在Ollama配置中启用CUDA支持

五、安全注意事项

  1. 端口防护
export OLLAMA_HOST=127.0.0.1  # 禁止外部访问
netstat -an | grep 11434      # 验证监听地址
  1. 防火墙规则
sudo ufw deny 11434/tcp      # 禁用Ollama外部端口

六、扩展应用场景

  1. 私有知识库:接入LangChain处理本地文档
  2. 自动化脚本:通过API实现代码生成/自动Debug
  3. 硬件控制:结合HomeAssistant实现语音智能家居

完整代码已开源(其实没有):GitHub仓库地址
通过本教程,您已掌握从模型部署到应用开发的全流程。本地化AI部署不仅降低成本,更保障了数据隐私,为开发者提供了真正的「AI自由」!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/70222.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

图论入门算法:拓扑排序(C++)

上文中我们了解了图的遍历(DFS/BFS), 本节我们来学习拓扑排序. 在图论中, 拓扑排序(Topological Sorting)是对一个有向无环图(Directed Acyclic Graph, DAG)的所有顶点进行排序的一种算法, 使得如果存在一条从顶点 u 到顶点 v 的有向边 (u, v) , 那么在排序后的序列中, u 一定…

第1章大型互联网公司的基础架构——1.2 客户端连接机房的技术1:DNS

客户端启动时要做的第一件事情就是通过互联网与机房建立连接&#xff0c;然后用户才可以在客户端与后台服务器进行网络通信。目前在计算机网络中应用较为广泛的网络通信协议是TCP/IP&#xff0c;它的通信基础是IP地址&#xff0c;因为IP地址有如下两个主要功能。 标识设备&…

Next.js【详解】CSS 样式方案

全局样式 Global CSS 默认已创建&#xff0c;即 src\app\globals.css&#xff0c;可根据需要修改 默认在全局布局中导入 src\app\layout.tsx import "./globals.css";组件样式 CSS Modules 新建文件 src\app\test\styles.module.css .red {color: red;}导入目标页面…

LVS相关原理

一、LVS集群的体系结构 1.1 LVS简介 LVS 是 Linux Virtual Server 的简称&#xff0c;也就是 Linux 虚拟服务器 , 是一个由章文嵩博士发起的自由软件项目&#xff0c;它的官方站点是 www.linuxvirtualserver.org 。现在 LVS 已经是 Linux标准内核的一部分&#xff0c;在Linux2…

【2025深度学习系列专栏大纲:深入探索与实践深度学习】

第一部分:深度学习基础篇 第1章:深度学习概览 1.1 深度学习的历史背景与发展轨迹 1.2 深度学习与机器学习、传统人工智能的区别与联系 1.3 深度学习的核心组件与概念解析 神经网络基础 激活函数的作用与类型 损失函数与优化算法的选择 1.4 深度学习框架简介与选择建议 第2…

Java与C语言中取模运算符%的区别对比

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: Java 文章目录 &#x1f4af;前言&#x1f4af;C语言中的取模运算符 %基本行为示例 注意事项示例&#xff1a;负数取模 &#x1f4af;Java中的取模运算符 %基本行为示例 对浮点数的支持示例&#xff1a;浮点数取模 符…

日常开发中,使用JSON.stringify来实现深拷贝的坑

使用JSON.stringify的方式来实现深拷贝的弊端 弊端一&#xff1a;无法拷贝NaN、Infinity、undefined这类值 无法拷贝成功的原因&#xff1a; 对于JSON来说&#xff0c;它支持的数据类型只有null、string、number、boolean、Object、Array&#xff0c;所以对于它不支持的数据类…

【Linux】Ubuntu Linux 系统——Node.js 开发环境

ℹ️大家好&#xff0c;我是练小杰&#xff0c;今天星期五了&#xff0c;同时也是2025年的情人节&#xff0c;今晚又是一个人的举个爪子&#xff01;&#xff01; &#x1f642; 本文是有关Linux 操作系统中 Node.js 开发环境基础知识&#xff0c;后续我将添加更多相关知识噢&a…

mysql 学习16 视图,存储过程,存储函数,触发器

视图&#xff0c; 存储过程&#xff0c; 存储函数 触发器

SpringBoot+Vue+数据可视化的动漫妆造服务平台(程序+论文+讲解+安装+调试+售后等)

感兴趣的可以先收藏起来&#xff0c;还有大家在毕设选题&#xff0c;项目以及论文编写等相关问题都可以给我留言咨询&#xff0c;我会一一回复&#xff0c;希望帮助更多的人。 系统介绍 在当今数字化高速发展的时代&#xff0c;动漫产业迎来了前所未有的繁荣&#xff0c;动漫…

开源语音克隆项目 OpenVoice V2 本地部署

#本机环境 WIN11 I5 GPU 4060ti 16G 内存 32G #开始 git clone https://github.com/myshell-ai/OpenVoice.git conda create -n opvenv python3.9 -y conda activate opvenv pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/…

【Prometheus】prometheus结合domain_exporter实现域名监控

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全…

rustdesk编译修改名字

最近&#xff0c;我用Rust重写了一个2W行C代码的linux内核模块。在此记录一点经验。我此前没写过内核模块&#xff0c;认识比较疏浅&#xff0c;有错误欢迎指正。 为什么要重写&#xff1f; 这个模块2W行代码量看起来不多&#xff0c;却在线上时常故障&#xff0c;永远改不完。…

在linux系统中安装Anaconda,并使用conda

系统 : ubuntu20.04 显卡&#xff1a;NVIDIA GTX1650 目录 安装Anaconda第一步&#xff1a;下载合适版本的Anconda1. 查看自己Linux的操作系统及架构命令&#xff1a;uname -a2. 下载合适版本的Anconda 第二步&#xff1a;安装Aanconda1. 为.sh文件设置权限2. 执行.sh文件2.1 .…

(前端基础)HTML(一)

前提 W3C:World Wide Web Consortium&#xff08;万维网联盟&#xff09; Web技术领域最权威和具有影响力的国际中立性技术标准机构 其中标准包括&#xff1a;机构化标准语言&#xff08;HTML、XML&#xff09; 表现标准语言&#xff08;CSS&#xff09; 行为标准&#xf…

9个用于测试自动化的最佳AI测试工具(2024)

选择一款优质的基于生成式AI人工智能的测试工具能够确保测试过程的准确性和效率&#xff0c;从而加速整个软件测试周期。相反&#xff0c;设计不佳的测试工具可能无法发现错误&#xff0c;并可能存在安全问题。它们可能产生误报或漏报&#xff0c;误导开发与测试团队&#xff0…

LabVIEW的吞雨测控系统

本案例介绍了一种基于LabVIEW开发的吞雨测控系统&#xff0c;该系统通过建模仿真分析不同控制器模式下的阶跃信号响应&#xff0c;从而选择了最适合的控制器。为了有效解决在控制流量过程中出现的振荡收敛和流量信号大扰动问题&#xff0c;系统采用了改进的积分分离PID算法&…

C++中的顺序容器(一)

文章目录 顺序容器概述所有容器类型都支持的操作迭代器容器定义与初始化将一个容器初始化为另一个容器的拷贝标准库array具有固定大小 赋值和swap关系运算符 顺序容器的特有操作向顺序容器添加元素访问元素删除元素特殊的forward_list操作改变容器的大小容器操作可能是迭代器失…

[论文阅读] SeeSR: Towards Semantics-Aware Real-World Image Super-Resolution

文章目录 一、前言二、主要贡献三、Introduction四、Methodology4.1 Motivation &#xff1a;4.2Framework Overview.** 一、前言 通信作者是香港理工大学 & OPPO研究所的张磊教授&#xff0c;也是图像超分ISR的一个大牛了。 论文如下 SeeSR: Towards Semantics-Aware Rea…

案例-04.部门管理-删除

一.功能演示 二.需求说明 三.接口文档 四.思路 既然是通过id删除对应的部门&#xff0c;那么必然要获取到前端请求的要删除部门的id。id作为请求路径传递过来&#xff0c;那么要从请求路径中获取&#xff0c;id是一个路径参数。因此使用注解PathVariable获取路径参数。 请求方…