章
目
录
本文将详细介绍如何纯前端调用DeepSeek V3模型,实现流式返回,并支持Markdown文本、表格、代码等多种格式展示。文末还提供了源码,方便大家深入研究。
一、技术栈与项目概述
本次制作的示例项目相对简易,耗时不到半天,主要基于react@18
、tailwindcss@3
、vite
以及react - markdown
等技术搭建而成。代码简洁易懂,重点在于帮助大家熟悉调用流程。接下来,先通过截图和视频展示项目成果,如果不符合您的预期,可随时关闭文章,以免耽误您的时间。
二、Demo功能详细介绍
- 流式调用DeepSeek V3:实现与DeepSeek V3模型的流式交互,让对话过程更加流畅自然。
- 布局优化:在主页面增加了会话历史记录功能,方便用户查看和回顾之前的对话内容,提升交互体验。
- Markdown文本展示支持:能够完美展示Markdown格式的文本,包括常见的标题、段落、列表等元素。
- 特殊Markdown展示支持:对
table
、ul
、link
等特殊Markdown格式提供支持,确保复杂内容的正确呈现。 - HTML结构回显:可以准确回显HTML结构,增强了内容展示的灵活性。
- 组件封装:专门封装了
chat - input
、用户问答
、AI回复
、md展示
等组件,使代码结构更加清晰,便于维护和扩展。 - 空白间隙优化:针对HTML结构回显时出现的空白间隙问题进行了优化,提升页面展示效果。
- 代码复制功能:具备代码复制功能,方便用户获取展示的代码内容。
三、Demo展示
在这个示例项目中,用户可以与DeepSeek V3模型进行多种类型的交互。比如,询问“你是什么模型”,模型会回复:“我是DeepSeek – V3,由深度求索(DeepSeek)公司开发的一款大语言模型(LLM) 。我的知识截止日期是2024年7月,支持128k上下文长度,可以处理文本理解、代码生成、逻辑推理、数学计算等多种任务。我目前是免费的,你可以随时向我提问!有什么我可以帮你的吗?”
当用户要求“使用JavaScript的reduce方法实现数组去重”时,模型会给出相应的代码示例及解释。还能根据需求生成表格,如“生成一个三行三列的表格,用于计算姓名和成绩”,模型会输出:
姓名 | 成绩 | 备注 |
---|---|---|
张三 | 85 | 数学 |
李四 | 92 | 英语 |
王五 | 78 | 物理 |
此外,对于列表展示、嵌套列表等需求,模型也能很好地支持。
四、实现步骤
- 注册DeepSeek API Key:首先需要前往DeepSeek API开放平台进行注册,并充值至少十块钱。在平台的“API keys”页面获取API Key,这个Key是调用模型的关键凭证,务必妥善保管,不要与他人共享或暴露在浏览器等客户端代码中,否则可能导致账户安全问题,平台可能会自动禁用泄露的API Key 。具体参考:如何获取 DeepSeek API?
- 写入API Key:克隆项目代码后,找到
.env
文件,将其中的VITE_DEEPSEEK_KEY
替换为自己获取到的API Key。 - 项目启动:在项目目录下的终端中执行以下命令启动项目:
npm i
npm run dev
- 测试问答:项目启动后,在问答框中输入一些问题来测试模型的支持情况,例如“你是什么模型”(用于测试纯文本回复)、“写一段js去重的代码”、“帮我生成一个三行三列的表格,用于计算姓名和成绩”等。
五、核心代码
(一)OpenAI SDK的使用
任何大模型的接口在一定程度上都兼容openai
的规范,我们可以借助openai sdk
来实现对DeepSeek模型的请求。以下代码通过开启dangerouslyAllowBrowser
属性,实现在浏览器中调用模型。不过需要注意,这种做法仅适用于示例项目,在实际项目中,为了安全考虑,建议由后端进行调用,避免API Key暴露。
import OpenAI from "openai";
const initOpenAI = () => {
openaiRef.current = new OpenAI({
baseURL: "https://api.deepseek.com",
apiKey: GlobalAPI.config?.VITE_DEEPSEEK_KEY,
dangerouslyAllowBrowser: true,
});
};
(二)Markdown – AI.tsx组件
import ReactMarkdown from "react-markdown";
import rehypeRaw from "rehype-raw";
import remarkGfm from "remark-gfm";
import rehypeHighlight from'rehype-highlight'; // 代码高亮
import 'highlight.js/styles/github.css';
<ReactMarkdown
remarkPlugins={[remarkGfm, remarkMath]}
rehypePlugins={[rehypeRaw, rehypeHighlight, removeExtraWhitespace]}
components={components as any}
>
{markdownstr}
</ReactMarkdown>
这段代码借助react - markdown
及其配套插件,实现了对Markdown文本的样式渲染、表格和HTML标签的支持,还利用rehypeHighlight
实现了代码高亮。具体的样式和功能配置可查看相关插件文档,这里的removeExtraWhitespace
是用于处理HTML渲染空白行问题的自定义插件。
(三)代码复制组件
通过react - markdown
自定义标签的方式,自定义了<pre>
标签,结合rehype - highlight
和copy - to - clipboard
实现了代码的高亮显示和复制功能。
import PreWithCopy from "./copycode.tsx"
// 自定义渲染器
const components = {
pre: PreWithCopy,
};
<ReactMarkdown
remarkPlugins={[remarkGfm, remarkMath]}
rehypePlugins={[rehypeRaw, rehypeHighlight, removeExtraWhitespace]}
components={components as any}
>
{markdownstr}
</ReactMarkdown>
(四)HTML渲染空白行处理
在使用react - markdown
并开启rehypePlugins rehypeRaw
时,由于模型返回的\n
过多,可能导致页面间距过大,尤其是在展示表格等内容时。为此,我们编写了以下代码来单独处理空白行问题:
// 消除空格的 解决html 渲染的问题
const removeExtraWhitespace = () => {
return (tree: any) => {
const removeWhitespace = (node: any) => {
if (node.tagName === "pre") {
return;
}
if (node.type === "text") {
node.value = node.value.replace(/\s+/g, " ");
}
if (node.children) {
node.children = node.children.filter((child: any) => {
if (child.type === "text") {
return child.value.trim()!== "";
}
removeWhitespace(child);
return true;
});
}
};
removeWhitespace(tree);
return tree;
};
};
这段代码通过遍历HTML树结构,对文本节点中的空白字符进行处理,并过滤掉多余的空白文本节点,有效解决了HTML渲染时的空白间隙问题。
六、总结
以上就是本次示例项目的主要功能和技术实现细节。整个项目基于React构建,如果您对Vue版本感兴趣,欢迎在评论区留言,项目的完整代码可在gitee仓库地址查看,希望这个示例能帮助大家快速了解和上手纯前端调用DeepSeek V3模型的技术。