你们可能不知道什么是md渲染,但一定见过与ai问答时AI回答中生成的代码块,一边输出还在一边自动更改字体的布局的样式。
为什么能做到这一点?
首先,字体的样式(css)可以放在html文件中,用<style>
标签包裹;也可以放在单独的css文件中(如.xml .style ),然后在html文件中引用。
但这些文件也可以被后缀为md
的文件所替代。md(Markdown)是一种纯文本格式,但在聊它之前,我们先简单了解一下什么是标记语言。
标记语言是什么?
标记语言(Markup Language)是一种用来给文本添加结构和样式的语言。它不像编程语言那样复杂,而是通过简单的标签或符号,告诉计算机如何显示内容。比如大家熟知的HTML(超文本标记语言),用<p>
表示段落,<h1>
表示标题,这些标签就是“标记”。标记语言的本质是让人和机器都能轻松读懂文本,同时赋予它格式化的能力。
Markdown 是什么?
Markdown(简称md)是一种轻量级的标记语言,它用纯文本写成,语法超级简单,比如用#表示标题,用*表示列表,用`````包裹代码块。它的目标是“易读易写”,既能让人直接看懂原始文本,又能被工具转换成漂亮的HTML页面。
这就是一个简单的用``` ```包裹就可以生成的代码块。
markdown能做到这一点的原因就是使用它的文字被解析为了HTML元素,交由浏览器渲染。
那为什么AI问答界面可以一边生成一边渲染呢
也很简单,就是每次接收到AI的回答后加入到原有文本中,程序将这段文本作为md文件重新解析为html元素,不断生成的过程就显得极具动态了。
具体用法
举例。因为开源的md渲染库不止一个。
<!--这里以`marked.js`为例,它是一个轻量级的md渲染库,可以直接在浏览器中运行。-->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Marked.js Demo</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/marked/marked.min.css">
</head>
<body>
<div id="content"></div>
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
并不是引用了就可以了,但使用方法非常简单,对需要渲染的文本进行marked()
处理,得到的结果就是html代码。
const text = "## 标题\n\n- 列表1\n- 列表2\n\n```javascript\nconsole.log('Hello, world!');\n```";
const html = marked(text); //或者const html = marked.parse(test)效果一样;
document.getElementById("content").innerHTML = html;
这样,就能在浏览器中看到渲染后的结果。
效果大概是:
标题
- 列表1
- 列表2
console.log('Hello, world!');
你可以在网页前端主动修改css让渲染后的内容更加美观。
而对于AI流式输出块
const assistantBuffer = ""; //这里是AI的回答缓冲,用于累加
//每隔一段时间,AI的回答会被加入到assistantBuffer中
//在每次添加消息时调用
messageDiv.innerHTML = marked.parse(assistantBuffer);
注意,如果你使用的messageDiv.content
累加文本,然后用marked渲染,可能导致渲染内容垂直排列,因为累加中的+
会被渲染为换行。
这也是为什么要单独拿出一个变量作为AI回答的缓冲。
当然也许有别的做法,我只是觉得这样简单。
此方悬停