Deepseek R1 安装及实现 Web 服务

힘센캥거루
2025년 2월 3일(수정됨)
7
108
Deepseek R1 安装及实现 Web 服务-1

看到中国把 Deepseek R1 以开源形式公开后,我也想在本地环境运行一次试试。

于是就尝试安装一下,并查了一下要怎么把它做成一个 Web 服务。

安装环境是MacBook M1 16Gb 机型

1. 安装 Ollama

Deepseek R1 安装及实现 Web 服务-2

Ollama是一个开源工具,可以让你在本地环境运行 LLM。

据说是用 Go 语言编写的,并且支持 JavaScript 和 Python API,因此既可以在 localhost 上使用,也可以对外部环境开放访问。

安装可以通过上面的网站下载安装程序,或者通过 homebrew 安装。

brew install ollama

果然还是用 Homebrew 安装的时候最爽。

为了这味道才用 MacBook。

然后启动服务。

brew services start ollama

2. Ollama 的简单用法

输入 Ollama help 就可以看到如下命令。

ollama help
Large language model runner

Usage:
  ollama [flags]
  ollama [command]

Available Commands:
  serve       Start ollama
  create      Create a model from a Modelfile
  show        Show information for a model
  run         Run a model
  stop        Stop a running model
  pull        Pull a model from a registry
  push        Push a model to a registry
  list        List models
  ps          List running models
  cp          Copy a model
  rm          Remove a model
  help        Help about any command

我们真正会用到的没几条。

如果服务器上已经有模型了,使用 run 就可以拉取模型并直接运行。

如果服务器上没有,也可以通过模型文件和 create 命令创建新的环境。

Deepseek R1 安装及实现 Web 服务-3

目前上线的版本有好几个,不过我首先想试试原版。

在终端中按下面这样输入。

如果想用别的模型:只需要把后半部分改掉就行。

ollama run deepseek-r1:8b

# 만일 다른 모델을 원한다면...
ollama run deepseek-r1:16b
ollama run deepseek-r1:7b
ollama run deepseek-r1:1.5b

3. 深入体验 Deepseek-R1 模型

我先运行了 8B 模型。

Deepseek R1 安装及实现 Web 服务-4

可惜这个模型对韩语理解得不太好。

相反,它对英文的回答相当不错。

could you recommend some places for travel

<think>
... 생략
</think>

Based on your thoughtful considerations and the various aspects you've
explored, here's a curated travel plan that combines historical sites,
natural beauty, unique cultural experiences, and culinary delights:

### Travel Itinerary: Exploring History, Nature, Culture & Cuisine

#### 1. **Historical Exploration**
   - **Amalfi Coast, Italy**: Visit Positano and Amalfi for their charming
architecture and coastal views. Explore ancient Roman ruins nearby.
   - **Tulum, Mexico**: Discover Mayan ruins and vibrant beach settings
with a mix of history and relaxation.

... 생략

### Budget Considerations:
   - Opt for multi-destination trips to balance costs. Prioritize
affordable flight and accommodation deals.

This itinerary offers a blend of history, nature, culture, and cuisine,
tailored to your interests and considerations.

Hugging Face 上可以找到更多的模型。

其中我下载并运行了一个量化的 14B 蒸馏模型

体积是 10.27Gb。

ollama create deepseek-r1:14b-distill -f DeepSeek-R1-Distill-Qwen-14B-Q5_K_S
ollama run deepseek-r1:14b-distill

然后我问了一句“你会说韩语吗?”。

한국말 할 수 있니?

<think>
Okay, the user is asking "한국말할 수 있니?" which means "Do I speak
Korean?" in Korean.

I need to confirm if they know Korean or not.

Since they're asking this, it's likely that they don't speak Korean well
but want to communicate with someone who does.

So, I'll respond in a friendly manner and offer my help.
</think>

한국말이 nNot very fluent, but I can try to help! What do you need?

老是报错或者输出怪怪的,后来翻文档才发现,这上面提供的模型两端必须加上 token

如果在ollama 中不设置 template、params 就无法正常运行。

Do not forget about <|User|> and <|Assistant|> tokens! - Or use a chat template formatter

在研究模板等设置方法时,我意识到直接用别人已经做好的东西下载下来更有利于身心健康

我下载了 8b 模型中最受欢迎的一个。

Deepseek R1 安装及实现 Web 服务-5
ollama run sjo/deepseek-r1-8b-llama-distill-abliterated-q8_0

这样一来,思考时间也变短了,回答也相当不错。

只是能感觉到 MacBook 越来越烫。

Deepseek R1 安装及实现 Web 服务-6

14b 量化模型几乎把内存拉满,但总算还能跑。

Deepseek R1 安装及实现 Web 服务-7

但是一跑原版,内存就疯狂飙升。

Deepseek R1 安装及实现 Web 服务-8

要想好好利用这些开源模型,感觉至少需要 32Gb 以上的配置。

那一刻我暗下决心要好好赚钱。

4. 使用 Vercel SDK 和 Ollama 实现 Deepseek-R1 服务

Deepseek R1 安装及实现 Web 服务-9

运行 Ollama 后,会打开 11434 端口。

可以直接向这个端口发起 API 请求!

先安装一个需要的库。

yarn add ollama-ai-provider

然后在 .env 中像下面这样添加 url。

OLLAMA_BASEURL="http://localhost:11434/api"

接着如下配置 API endpoint。

import { streamText } from "ai";
import { createOllama } from "ollama-ai-provider";

export const maxDuration = 30;

export async function POST(req: Request) {
  const { messages } = await req.json();
  const ollama = createOllama({
    baseURL: process.env.OLLAMA_BASEURL,
  });

  const result = await streamText({
    model: ollama("deepseek-r1:1.5b-distill"),
    // create로 만든 모델 명을 넣어주면 됨.
    // 서버 램이 적어서 1.5b 모델로 구현해 봄.
    messages: messages,
  });
  return result.toDataStreamResponse();
}

然后再创建一个 client 页面。

就是沿用了上一篇文章中带 Markdown 的响应页面。

不同之处只有 api 地址变了。

"use client";
import { useChat } from "ai/react";
import { PaperAirplaneIcon, StopCircleIcon } from "@heroicons/react/24/outline";
import { useRef, useEffect } from "react";
import ReactMarkdown from "react-markdown";
import remarkGfm from "remark-gfm";
import rehypeHighlight from "rehype-highlight";
import "highlight.js/styles/atom-one-dark.css";

export default function ChatInterface() {
  const { messages, input, handleInputChange, handleSubmit, isLoading } =
    useChat({
      api: "/api/services/deepseek",
    });
  const messagesEndRef = useRef<HTMLDivElement>(null);
  const scrollToBottom = () => {
    messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
  };

  useEffect(() => {
    scrollToBottom();
  }, [messages.length]);

  return (
    <div className="flex flex-col h-[calc(100svh-60px)] lg:h-[calc(100svh-106px)] max-w-3xl mx-auto border rounded-lg shadow-lg bg-white">
      <div className="flex-1 overflow-y-auto p-4 space-y-4">
        {messages.map((message) => {
          if (message.role !== "system") {
            return (
              <div
                key={message.id}
                className={`p-3 rounded-lg  ${
                  message.role === "user"
                    ? "ml-auto bg-blue-100"
                    : message.role === "assistant"
                    ? "bg-gray-100"
                    : "bg-green-100"
                }`}
              >
                {message.role === "assistant" && (
                  <p className="font-black mb-1">🌏 AI</p>
                )}
                <div className="text-gray-800">
                  <ReactMarkdown
                    className="w-full h-5/6 prose
                       prose-ol:bg-gray-200 prose-ol:rounded-lg prose-ol:pr-1.5 prose-ol:py-3
                     prose-ul:bg-gray-200 prose-ul:rounded-lg prose-ul:pr-1.5 prose-ul:py-3
                     prose-blockquote:bg-gray-200 prose-blockquote:rounded-lg prose-blockquote:border-l-8
                     prose-blockquote:text-gray-600 prose-blockquote:border-gray-700 prose-blockquote:break-all prose-blockquote:pr-1.5
                     prose-a:text-blue-600 prose-a:underline-offset-4 prose-a:underline
                      "
                    remarkPlugins={[remarkGfm]}
                    rehypePlugins={[rehypeHighlight]}
                  >
                    {message.content}
                  </ReactMarkdown>
                </div>
              </div>
            );
          }
        })}
        <div ref={messagesEndRef} />
      </div>

      <div className="fixed bottom-0 left-0 right-0 flex justify-center">
        <div className="w-full max-w-3xl p-1 bg-white border rounded-lg">
          <form
            onSubmit={handleSubmit}
            className="flex items-center bg-gray-50 rounded-lg px-4 py-2"
          >
            <input
              value={input}
              onChange={handleInputChange}
              placeholder="请输入消息..."
              className={`flex-1 bg-transparent outline-none resize-none max-h-32`}
              disabled={isLoading}
            />

            {isLoading ? (
              <button className="ml-2 text-blue-500 p-1 rounded-full hover:bg-blue-50">
                <StopCircleIcon className="size-6" />
              </button>
            ) : (
              <button
                type="submit"
                className="ml-2 text-blue-500 p-1 rounded-full hover:bg-blue-50"
              >
                <PaperAirplaneIcon className="size-6" />
              </button>
            )}
          </form>
        </div>
      </div>
    </div>
  );
}

现在来看看它的响应。

Deepseek R1 安装及实现 Web 服务-10

前面没有 <think> 稍微有点可惜,但总体上还能跑。

接下来就只剩下慢慢打磨了。

5. 后记

Deepseek R1 安装及实现 Web 服务-11

Deepseek R1 发布之后,我一度觉得好像出现了平价版的 Jarvis,但实际体验还没到那个程度。

至少如果想要达到和 ChatGPT 相近的性能,就需要与之相配的硬件,而这种硬件配置对普通人来说门槛还是有点高。

不过,敢把这种东西开源出来,本身就已经非常了不起。

期待在不久的将来,能出现既能在低配置上运行、又针对韩语做过微调的模型。

관련 글

Next.js 全栈博客开发记
Next.js 全栈博客开发记
在第一次接触网页开发大约 1 年之后,我开始想着想要拥有一个属于自己的博客。于是我就大概花了 6 个月几乎只埋头做这件事。前端部分的功能,参考金度亨先生的博客就已经足够了。我用 mdx 搭建起一个博客,其实连一周都没花到。事实上,仅靠前端也并不会给博客运营带来什么大问题。有一阵子我也觉得,只要写 m...
使用 Caddy 实现 Next.js 无停机部署(本地服务器)
使用 Caddy 实现 Next.js 无停机部署(本地服务器)
每次一有想在主页上加点什么的念头就去 build,结果中间好像偶尔会有人访问。于是 Search Console 上的分数开始一点点往下掉。觉得这样不行,就开始思考要怎么做无停机部署。1. 两个项目文件夹 + 两个终端答案出乎意料地简单:开两个终端。在一个终端里 build,另一个终端里让服务器跑着...
谷歌搜索索引自动化 - Web Search Indexing API
谷歌搜索索引自动化 - Web Search Indexing API
继上次搞完 IndexNow 之后,也决定在谷歌这边做一下自动化。查了一下,发现谷歌是通过一个叫 Web Search Indexing 的 API 来支持这个功能的。1. 适用范围官方文档中,这个 API 正式支持的范围是招聘公告和流媒体视频服务。说是为了给对实时性要求高的内容创建索引用的,但搜了...
搜索索引生成自动化 - IndexNow
搜索索引生成自动化 - IndexNow
在向 Bing 提交站点收录时才发现,Bing 提供了一个叫做 IndexNow 的功能。核心在于,可以利用 API Key,在写完文章的瞬间就立刻发起索引请求。只要用 fetch 写出类似下面这样的请求,并把它串联到「写文章」流程里,就可以在把文章保存到 DB 的同时发送索引生成请求。POST /...
被入侵的 Nextjs、React 服务器经历
被入侵的 Nextjs、React 服务器经历
我最初接触到这次安全问题是在 12 月 5 日凌晨。据说在 React 中可以在未认证的情况下进行远程代码执行。看到这条新闻后,我虽然告诉了别人,但总觉得自己应该没事,就什么想法也没有地略过了。1. 发现被入侵的痕迹结果当我想登录更新博客代码时,在终端里发现了有命令被执行过的痕迹。/bin/sh:...
在博客中添加多语言功能(NextJS、next-intl、Vercel AI SDK)
在博客中添加多语言功能(NextJS、next-intl、Vercel AI SDK)
最近我觉得博客需要多语言功能。于是决定用 next-intl 来实现多语言服务。1.i18n首先,在做多语言服务时有一些必须遵守的原则。这被称为 internationalization,单词太长,所以把首字母 i 和尾字母 n,以及中间 18 个字母合在一起,写成 i18n。1) i18n 的原则...

댓글을 불러오는 중...