小恐龙 🦕、羊驼 🦙 和鲸鱼 🐋
这是使用 Deno 构建 LLM 系列的第一部分。点击此处查看第二部分。
我一直想了解如何与本地托管的大型语言模型进行交互,而推理模型 DeepSeek R1 的发布足以促使我着手解决这个问题。
我的日常工作是 CTO Labs 的首席技术专家,我们为投资者、高级管理人员和董事会提供技术咨询。一个始终备受关注的话题是新兴技术对组织的影响,目前没有比 AI 更大的技术话题了。我们保持对这些影响敏感的一种方式是探索我们自己的实际用例。
虽然我知道 Python 是数据、机器学习和 AI 领域的“事实标准”语言,但我对 TypeScript/JavaScript 在该领域的现状也很好奇,因为对我个人而言,它们更熟悉。虽然我作为 Deno 的前核心贡献者存在偏见,但我一直很喜欢 Deno 作为开发工具的“开箱即用”方法。
我也对 Jupyter notebooks 很好奇,我所有的数据科学家同事都是它们的坚定拥护者,而当我是 Deno 的核心贡献者时,我曾强烈主张将内核支持集成到 Deno 中,但我从未有过一个促使我亲自尝试的用例。
我最喜欢的开发工具,加上一个专门适用于这项任务的开发环境,是否能成为学习和试验 AI 的简单方式?跳到最后,答案是肯定的。
我将带你踏上我曾走过的旅程……
开始
我们的旅程包含几个组成部分
- 语言模型环境 – 尽管你可以通过 API 连接到各种 LLM 托管环境,但我们将利用 Ollama 框架在本地机器上运行语言模型。
- 大型语言模型 – 我们将使用 DeepSeek R1 的一个本地可运行的调整版本。
- Jupyter Notebook – 用于交互式代码和文本。
- Deno – 一个包含内置 Jupyter 内核的运行时。我们假设已安装最新版本。安装。
- 集成开发环境 (IDE) – 我们将使用 VSCode,它内置了 Jupyter Notebook 支持和 Deno 扩展(扩展链接)。
- AI 库/框架 – LangChain.js 用于简化与 LLM 的交互。
- 模式验证器 – 我们将结构化 LLM 输出。为此我们将使用 zod。
性能因您的 CPU/GPU 和内存而异。请确保您有足够的内存和处理能力来运行本地模型。
设置本地模型
如果尚未安装,请下载并安装 Ollama。确认 `ollama` 命令可用且 Ollama 服务器正在端口 11434 上运行。
安装 DeepSeek R1 8b 参数模型
ollama pull deepseek-r1:8b
使用以下命令检查可用性
ollama list
创建 Notebook
- 打开 VSCode。为您的 Notebook 创建一个新文件夹或路径。
- 安装/更新 Deno VSCode 扩展。通过命令面板中的“Deno: Enable”命令启用它,或创建一个 `deno.json` 文件。
- 使用“Create: New Jupyter Notebook”命令,并在“Select Kernel”菜单中选择 Deno。如果列表中没有 Deno,请更新或重新安装 Deno 扩展。
使用模型
LangChain.js 提供了一个与大型语言模型(包括 Ollama)交互的一致接口。例如:
import { ChatOllama } from "npm:@langchain/ollama";
const model = new ChatOllama({
model: "deepseek-r1:8b",
});
生成一个链
LangChain.js 使创建模块化 AI 工作流或“链”变得更容易。
import { z } from "npm:zod";
import { RunnableSequence } from "npm:@langchain/core/runnables";
import { StructuredOutputParser } from "npm:@langchain/core/output_parsers";
import { ChatPromptTemplate } from "npm:@langchain/core/prompts";
const zodSchema = z.object({
answer: z.string().describe("answer to the user's question"),
source: z.string().describe(
"source used to answer the user's question, should be a website.",
),
});
const parser = StructuredOutputParser.fromZodSchema(zodSchema);
const chain = RunnableSequence.from([
ChatPromptTemplate.fromTemplate(
"Answer the users question as best as possible.\n{format_instructions}\n{question}",
),
model,
parser,
]);
// Display the format instructions
Deno.jupyter.md`${parser.getFormatInstructions()}`;
JSON 模式示例
下面是一个有效 JSON 模式的示例,用于表示一个需要 `foo` 属性为字符串数组的对象
{
"type": "object",
"properties": {
"foo": {
"description": "a list of test words",
"type": "array",
"items": {
"type": "string"
}
}
},
"required": ["foo"],
"$schema": "https://json-schema.fullstack.org.cn/draft-07/schema#"
}
因此,对象 `{"foo": ["bar", "baz"]}` 符合该模式。而对象 `{"properties": {"foo": ["bar", "baz"]}}` 则无效。
在上面的链中,任何输出都会被 `zod` 解析和验证。您的 LLM 的 JSON 必须与模式完全匹配。
以下是您的输出在此示例中必须遵循的 JSON 模式实例
{
"type": "object",
"properties": {
"answer": {
"type": "string",
"description": "answer to the user's question"
},
"source": {
"type": "string",
"description": "source used to answer the user's question, should be a website."
}
},
"required": ["answer", "source"],
"additionalProperties": false,
"$schema": "https://json-schema.fullstack.org.cn/draft-07/schema#"
}
记录我们的过程
LangChain.js、Deno 和 Jupyter 可以可视化地记录流程
const image = await chain.getGraph().drawMermaidPng();
const arrayBuffer = await image.arrayBuffer();
Deno.jupyter.image(new Uint8Array(arrayBuffer));
渲染效果如下所示:
提问
尝试提问
const response = await chain.invoke({
question: "What is a Deno?",
format_instructions: parser.getFormatInstructions(),
});
console.log(response);
示例输出
{
"answer": "Deno is a runtime environment designed for web development...",
"source": "https://deno.dev"
}
总结
我发现 Deno 和 Jupyter 为本地 AI 实验提供了一个有趣且高效的环境。大部分设置都与在本地运行 LLM 相关,这可以很容易地替换为基于 API 的模型,例如 OpenAI 或 Anthropic。
我早就知道 Deno 的“低摩擦”特性,现在我又看到了 Jupyter Notebook 在迭代探索和详尽文档方面的优势。它已成为我学习和原型开发的常用环境。
您在使用 Deno 运行 LLM 吗?🐋 🦕 🦙 我们期待您的反馈!