惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

U
Unit 42
Vercel News
Vercel News
博客园 - 叶小钗
大猫的无限游戏
大猫的无限游戏
MyScale Blog
MyScale Blog
P
Proofpoint News Feed
量子位
Engineering at Meta
Engineering at Meta
B
Blog RSS Feed
博客园 - 【当耐特】
Recent Announcements
Recent Announcements
Google DeepMind News
Google DeepMind News
D
DataBreaches.Net
Stack Overflow Blog
Stack Overflow Blog
博客园 - 聂微东
小众软件
小众软件
Hugging Face - Blog
Hugging Face - Blog
人人都是产品经理
人人都是产品经理
IT之家
IT之家
T
The Blog of Author Tim Ferriss
Last Week in AI
Last Week in AI
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Jina AI
Jina AI
博客园 - 三生石上(FineUI控件)

Deno

Deno 2.8 | Deno Claw Patrol: an open-source security firewall for agents | Deno Fresh 2.3: Zero JS by default, View Transitions, and Temporal support | Deno Deno 2.7: Temporal API, Windows ARM, and npm overrides | Deno Build a dinosaur runner game with Deno, pt. 6 | Deno Build a dinosaur runner game with Deno, pt. 5 | Deno Deno Deploy is Generally Available | Deno Introducing Deno Sandbox | Deno Build a dinosaur runner game with Deno, pt. 4 | Deno Build a dinosaur runner game with Deno, pt. 3 | Deno Build a dinosaur runner game with Deno, pt. 2 | Deno React / Next.js Denial-of-Service Vulnerability: Deno Deploy users protected | Deno Deno 2.6: dx is the new npx | Deno Build a dinosaur runner game with Deno, pt. 1 | Deno React Server Functions / Next.js Vulnerability: Deno Deploy users protected | Deno My highlights from the new Deno Deploy | Deno Deno's Other Open Source Projects | Deno How Deno protects against npm exploits | Deno Help Us Raise $200k to Free JavaScript from Oracle | Deno Deno 2.5: Permissions in the config file | Deno Fresh 2.0 Graduates to Beta, Adds Vite Support | Deno Deno 2.4: deno bundle is back | Deno JavaScript™ Trademark Update | Deno What's coming to JavaScript | Deno A brief history of JavaScript | Deno Reports of Deno's Demise Have Been Greatly Exaggerated | Deno An Update on Fresh | Deno How Plaid migrated 100 services to a new database platform 5x faster with Deno | Deno Deno 2.3: Improved deno compile, local npm packages, and more | Deno Add JSR packages with pnpm and Yarn | Deno
The Dino 🦕, the Llama 🦙, and the Whale 🐋 | Deno
Kitson Kelly · 2025-02-27 · via Deno

This is part 1 of a series on building LLMs with Deno. View the second part here.


I have had a desire for a while to understand what it would take to be able to interact with a locally hosted large language model and with the release of DeepSeek R1, a reasoning model, was enough of a prompt to figure out how to tackle it.

My day job is a Principal Technologist at CTO Labs, where we advise investors, senior executives and boards on technology. A topic that is always of interest is the impacts of emergent technologies on organizations, and at the moment there is no bigger technology topic than AI. One of the ways we keep fresh on those impacts is our own real world use cases.

Or view the accompanying tutorial on YouTube.

While I knew Python is the de facto language of data, ML and AI, I was also curious about the state of TypeScript/JavaScript in the space as well, because that is personally a lot more familiar to me. While I am biased, being a former core contributor to Deno, I have always liked the “batteries included” approach to being a development tool.

I was also curious about Jupyter notebooks, all my data scientist colleagues were strong advocates of them, and when I was a core contributor at Deno, I strongly advocated for us to pursue kernel support integrated into Deno, but I never had a personal use case that drove me to experiment with it.

Could my favorite development tool, plus a development environment specifically suited to the task, be an easy way to learn and experiment with AI? Skipping to the end, the answer is yes.

I am going to take you on the journey that I went on…

Getting started

There are a few components to our journey:

  • An environment for our language model – while you can connect up to various LLM hosting environments via APIs, we are going to leverage the Ollama framework for running language models on your local machine.
  • A large language model – we will use a resized version of DeepSeek R1 that can run locally.
  • A notebookJupyter Notebook for interactive code and text.
  • Deno – a runtime that includes a built-in Jupyter kernel. We assume a recent version is installed.
  • An IDE – we’ll use VSCode with built-in Jupyter Notebook support and the Deno extension (extension link).
  • An AI library/frameworkLangChain.js to simplify interactions with the LLM.
  • A schema validator – we’ll structure LLM output. We will use zod for this.

Performance varies based on your CPU/GPU and RAM. Ensure you have enough memory and processing power for local models.

Setting up a local model

Download and install Ollama if you haven’t already. Confirm the ollama command is available and the Ollama server is running on port 11434.

Install DeepSeek R1 8b parameter model:

ollama pull deepseek-r1:8b

Check availability with:

Creating a notebook

  1. Open VSCode. Create a new folder or path for your notebook.
  2. Install/update the Deno VSCode extension. Enable it with the Deno: Enable command from the palette, or create a deno.json.
  3. Use the Create: New Jupyter Notebook command and select Deno in the Select Kernel menu. If Deno isn’t listed, update or reinstall the Deno extension.

Using the model

LangChain.js provides a consistent interface for interacting with large language models, including Ollama. For example:

import { ChatOllama } from "npm:@langchain/ollama";

const model = new ChatOllama({
  model: "deepseek-r1:8b",
});

Generating a chain

LangChain.js makes it easier to create modular AI workflows, or “chains.”

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,
]);


Deno.jupyter.md`${parser.getFormatInstructions()}`;

Example JSON schema

Below is an example of a valid JSON schema for an object requiring a foo property that is an array of strings:

{
  "type": "object",
  "properties": {
    "foo": {
      "description": "a list of test words",
      "type": "array",
      "items": {
        "type": "string"
      }
    }
  },
  "required": ["foo"],
  "$schema": "http://json-schema.org/draft-07/schema#"
}

So the object {"foo": ["bar", "baz"]} matches the schema. The object {"properties": {"foo": ["bar", "baz"]}} is not valid.

In our chain above, any output is parsed and validated by zod. Your LLM’s JSON must match the schema exactly.

Here is the JSON schema instance your output must adhere to in this example:

{
  "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": "http://json-schema.org/draft-07/schema#"
}

Documenting our process

LangChain.js, Deno and Jupyter can document the flow visually:

const image = await chain.getGraph().drawMermaidPng();
const arrayBuffer = await image.arrayBuffer();

Deno.jupyter.image(new Uint8Array(arrayBuffer));

Which renders something like:

The langchain process output

Asking a question

Try asking a question:

const response = await chain.invoke({
  question: "What is a Deno?",
  format_instructions: parser.getFormatInstructions(),
});

console.log(response);

Sample output:

{
  "answer": "Deno is a runtime environment designed for web development...",
  "source": "https://deno.dev"
}

In the end

I found that Deno and Jupyter provide a fun, productive environment for local AI experiments. Most setup was related to running an LLM locally, which could easily be swapped for an API-based model like OpenAI or Anthropic.

I already knew how low-friction Deno can be, and now I’ve seen the benefits of Jupyter Notebooks for iterative exploration and thorough documentation. It’s become my go-to environment for learning and prototyping.

Using LLMs with Deno? 🐋 🦕 🦙 We want to hear from you!

Let us know on Twitter, Discord, YouTube, BlueSky, or Mastodon.