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

推荐订阅源

V
Visual Studio Blog
IT之家
IT之家
F
Fortinet All Blogs
腾讯CDC
酷 壳 – CoolShell
酷 壳 – CoolShell
月光博客
月光博客
GbyAI
GbyAI
Recent Announcements
Recent Announcements
博客园 - 叶小钗
H
Hackread – Cybersecurity News, Data Breaches, AI and More
博客园 - 司徒正美
Y
Y Combinator Blog
人人都是产品经理
人人都是产品经理
N
Netflix TechBlog - Medium
博客园_首页
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
爱范儿
爱范儿
F
Full Disclosure
博客园 - 【当耐特】
V
V2EX
M
MIT News - Artificial intelligence
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
G
Google Developers Blog
Stack Overflow Blog
Stack Overflow Blog
D
DataBreaches.Net
Martin Fowler
Martin Fowler
Cisco Talos Blog
Cisco Talos Blog
大猫的无限游戏
大猫的无限游戏
T
The Blog of Author Tim Ferriss
S
Schneier on Security
Latest news
Latest news
S
Secure Thoughts
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Hugging Face - Blog
Hugging Face - Blog
P
Proofpoint News Feed
Apple Machine Learning Research
Apple Machine Learning Research
T
Tenable Blog
Blog — PlanetScale
Blog — PlanetScale
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Cyberwarzone
Cyberwarzone
Spread Privacy
Spread Privacy
K
Kaspersky official blog
L
Lohrmann on Cybersecurity
宝玉的分享
宝玉的分享
A
About on SuperTechFans
Jina AI
Jina AI
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
P
Palo Alto Networks Blog
Microsoft Azure Blog
Microsoft Azure Blog

Pierce Freeman

A browser for agents | Pierce Freeman The grey market of podcast appearances The way I travel | Pierce Freeman Fixing slow AWS uploads | Pierce Freeman Local tools should still use vaults We solved scratch content first Starting a podcast in 2025 Being late but still being early Automating our home video imports Adding my parents to tailscale A deep dive on agent sandboxes Language servers for AI | Pierce Freeman My simple home podcast studio We need centralized infrastructure | Pierce Freeman Coercing agents to follow conventions using AST validation My unified theory of social selling My personal backup strategy | Pierce Freeman July updates to the homelab How the KV Cache works httpx is the right way to do web requests in Python Reputation is becoming everything | Pierce Freeman Building a (kind of) invisible mac app Updated knowledge in language models Making an ascii animation | Pierce Freeman How speculative decoding works | Pierce Freeman Under the hood of Claude Code Doing things because they're easy, not hard Speeding up sideeffects with JIT in mountaineer Firehot for hot reloading in Python Misadventures in Python hot reloading How text diffusion works | Pierce Freeman The tenacity of modern LLMs The ergonomics of rails | Pierce Freeman How language servers work | Pierce Freeman Just add eggs | Pierce Freeman Unfortunately SEO still matters | Pierce Freeman The futility of human-only web requirements Setting up Input Leap | Pierce Freeman Checking in on Waymo | Pierce Freeman The react revolution | Pierce Freeman Speeding up many small transfers to a unifi nas Quick notes on swift libraries AI engineering is a different animal San Francisco | Pierce Freeman Debugging a mountaineer rendering segfault Local network config on macOS Building our home network | Pierce Freeman Introducing Envelope.dev | Pierce Freeman Typehinting from day-zero | Pierce Freeman Generating database migrations with acyclic graphs Lofoten | Pierce Freeman Mountaineer v0.1: Webapps in Python and React Constraining LLM Outputs | Pierce Freeman Passthrough above all | Pierce Freeman Accuracy in kudos | Pierce Freeman How quick we are to adapt The curious case of LM repetition Costa Rica | Pierce Freeman Debugging chrome extensions with system-level logging Speeding up runpod | Pierce Freeman Inline footnotes with html templates Parsing Common Crawl in a day for $60 An era of rich CLI All or nothing with remote work The Next 10 Years | Pierce Freeman Adding wheels to flash-attention | Pierce Freeman LLMs as interdisciplinary agents | Pierce Freeman New Zealand | Pierce Freeman Representations in autoregressive models | Pierce Freeman Let's talk about Siri | Pierce Freeman Minimum viable public infrastructure | Pierce Freeman Reasoning vs. Memorization in LLMs Automatically migrate enums in alembic Greater sequence lengths will set us free On learning to ski | Pierce Freeman Dolomites | Pierce Freeman Using grpc with node and typescript Opportunity years | Pierce Freeman Buzzword peaks and valleys | Pierce Freeman Buenos Aires | Pierce Freeman Network routing interaction on MacOS Independent work: November recap | Pierce Freeman Debugging slow pytorch training performance The provenance of copy and paste Debugging tips for neural network training Patagonia | Pierce Freeman Santiago | Pierce Freeman My 2022 digital travel kit AWS vs GCP - GPU Availability V2 Independent work: October recap | Pierce Freeman Planning Patagonia | Pierce Freeman Relationship modeling | Pierce Freeman The power of status updates A new chapter | Pierce Freeman Give my library a coffee shop AWS vs GCP - GPU Availability V1 Switzerland | Pierce Freeman Headfull browsers beat headless | Pierce Freeman Webcrawling tradeoffs | Pierce Freeman Copenhagen | Pierce Freeman
Legacy code and AI copilots
2024-07-11 · via Pierce Freeman

Code LLMs seemingly have a much more difficult task than freeform writing. Since programs need to conform to language specification, code generation is incredible sensitive to small issues. A missing comma or a missing argument results in a program fully not working; it's often a binary choice. When writing prose, the worst downside is a stilted paragraph or a few missing commas. Given that programming fluency is required training data alone (versus more formal guarantees like [constrainted grammars](./Should you fine tune for JSON output?.md)) it's miraculous they work as well as they do.

In addition to the core language1, code LLMs also have to interplay with an ecosystem of constantly changing dependencies. These package versions constantly change in features, with different functions and syntax. To further complicate matters, LLMs are typically unaware of the dependency versions of the code that it's being trained on. They take all source files as independent examples. Github's Copilot tries to address this at runtime by building a .h-like representation of the functions that can be called from the current file. But not everything can be expressed in function calls alone.

Back when I was working on a few Next.js prototypes, I spent a lot of time using their new app based router convention. I won't dive into all the differences since the topic at hand is language modeling, not Javascript. But just for reference, a quick comparison between the two approaches.

This is the page router:

import { fetchData } from '../lib/data';

export default function Page({ serverData }) => {
  return (
    <div>
        <h1>Server-side Rendered Page</h1>
        <pre>{JSON.stringify(serverData, null, 2)}</pre>
    </div>
  );
};

export async function getServerSideProps() {
  const data = await fetchData();

  return {
    props: {
      serverData: data
    }
  };
}

And this is the app router, first introduced in Next.js 13:

import { fetchData } from '../lib/data';

export default async function Page() {
	const data = await fetchData();
	return (
		<div>
			<h1>Server-side Rendered Page</h1>
			<pre>{JSON.stringify(data, null, 2)}</pre>
		</div>
	);
}

The app router is clearer to write and can introduce some conditional switches in the view that's rendered, which can be convenient for more complicated interfaces. There's solid documentation available that walks through the most common use cases.

Before GPT4 was updated2, this app router was too new of a paradigm and wasn't included in their training data. ChatGPT was therefore unable to generate app router logic, and even when I added examples to a prompt manually, it would have a higher incidence of generation errors than the equivalent page router code. But even now when it's included, it's too dwarfed by the older corpus.

Probing GPT's knowledge

The below chat is with the current GPT-4 version. It still defaults to page based router examples even when the app router is clearly specified:


Me: Write me a standard server and client boilerplate function for next.js's app based router. It should use server side rendering to render the page. Make sure to use the app based router.


GPT:

Sure! Below is a basic example of a Next.js app with server-side rendering (SSR) using the App Router. This example includes a server component, a client component, and a Next.js page that uses SSR to render the page.

First, let's set up the project structure:

/my-next-app
  /pages
    /_app.js
    /index.js
  /components
    /ServerComponent.js
    /ClientComponent.js
  /styles
    /globals.css
  package.json
  next.config.js

Step 1: Set Up the package.json File

Create a package.json file for your project if you don't have one:

{
  "name": "my-next-app",
  "version": "1.0.0",
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start"
  },
  "dependencies": {
    "next": "latest",
    "react": "latest",
    "react-dom": "latest"
  }
}

Step 2: Install Dependencies

Run the following command to install the necessary dependencies:

npm install

Step 3: Create the Server Component

Create a file named ServerComponent.js in the components directory:

// components/ServerComponent.js
import React from 'react';

const ServerComponent = ({ data }) => {
  return (
    <div>
      <h1>Server Component</h1>
      <p>Data from server: {data}</p>
    </div>
  );
};

export default ServerComponent;

Step 4: Create the Client Component

Create a file named ClientComponent.js in the components directory:

// components/ClientComponent.js
import React from 'react';

const ClientComponent = () => {
  return (
    <div>
      <h1>Client Component</h1>
      <p>This is rendered on the client side.</p>
    </div>
  );
};

export default ClientComponent;

Step 5: Create the Custom App Component

Create a file named _app.js in the pages directory:

// pages/_app.js
import '../styles/globals.css';

function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />;
}

export default MyApp;

Step 6: Create the Page Component with SSR

Create a file named index.js in the pages directory:

// pages/index.js
import React from 'react';
import ServerComponent from '../components/ServerComponent';
import ClientComponent from '../components/ClientComponent';

const Home = ({ serverData }) => {
  return (
    <div>
      <ServerComponent data={serverData} />
      <ClientComponent />
    </div>
  );
};

export async function getServerSideProps() {
  // Fetch data from an external API or perform other server-side operations here
  const serverData = 'Hello from the server!';

  return {
    props: {
      serverData
    }
  };
}

export default Home;

The getServerSideProps is not used within the app router convention. This example still uses the format of the old page router convention. Not a surprise given the training data is highly tilted towards the page convention, which was in the wild for way longer.

If you then follow-up to correct the model, however, then it does get it correct:


Me: No, this is not the app convention. This is the page convention.


Got it, I understand now that you are looking for the app directory-based structure that was introduced in Next.js 13. Here is a boilerplate setup using the app-based router with server-side rendering (SSR).

Step 1: Set Up Project Structure

Create the following project structure:

/my-next-app
  /app
    /page.js
    /layout.js
    /server-component.js
    /client-component.js
  /styles
    /globals.css
  package.json
  next.config.js

Step 2: Set Up the package.json File

Create a package.json file for your project if you don't have one:

{
  "name": "my-next-app",
  "version": "1.0.0",
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start"
  },
  "dependencies": {
    "next": "13.0.0",
    "react": "18.0.0",
    "react-dom": "18.0.0"
  }
}

Step 3: Install Dependencies

Run the following command to install the necessary dependencies:

npm install

Step 4: Create the Server Component

Create a file named server-component.js in the app directory:

// app/server-component.js
import React from 'react';

const ServerComponent = ({ data }) => {
  return (
    <div>
      <h1>Server Component</h1>
      <p>Data from server: {data}</p>
    </div>
  );
};

export default ServerComponent;

Step 5: Create the Client Component

Create a file named client-component.js in the app directory:

// app/client-component.js
'use client';
import React from 'react';

const ClientComponent = () => {
  return (
    <div>
      <h1>Client Component</h1>
      <p>This is rendered on the client side.</p>
    </div>
  );
};

export default ClientComponent;

Step 6: Create the Root Layout

Create a file named layout.js in the app directory:

// app/layout.js
import '../styles/globals.css';

export default function RootLayout({ children }) {
  return (
    <html>
      <head>
        <title>My Next.js App</title>
      </head>
      <body>{children}</body>
    </html>
  );
}

Step 7: Create the Page Component with SSR

Create a file named page.js in the app directory:

// app/page.js
import React from 'react';
import ServerComponent from './server-component';
import ClientComponent from './client-component';

async function fetchServerData() {
  // Simulate fetching data from an external API
  return 'Hello from the server!';
}

export default async function Page() {
  const serverData = await fetchServerData();

  return (
    <div>
      <ServerComponent data={serverData} />
      <ClientComponent />
    </div>
  );
}

It takes additional nudging to encourage it to explore other areas of its weight space. And that's assuming that the models even have coverage of the latest frameworks within their training corpus. What if they don't?

Crawling is key

LLMs are notoriously data hungry. That's true in general, but that's particularly important for keeping updated on the latest nuances of programming libraries.

This is one place where Google still holds a pretty key advantage. I think it's undisputed that their search architecture is still the most sophisticated around. Jeffery Dean invented MapReduce just to handle the data volume. But an experienced team could quickly eat away at any particulars of their crawling advantage.3 Even an implementation that's 90% as good would still be able to collect the majority of data that's available online.

But Google's advantage isn't just technical. It's also cultural and economically incentivized. Most websites want to be found by Google. Maybe this is for product discovery, maybe it's to expand the reach of high quality content, or maybe it's paid SEO. But regardless of the reason - you usually want Google to crawl your websites because you want people to click into your domain and become legitimate traffic. Even if you don't love Google indexing your content, you'll usually put up with it anyway. The juice is worth the squeeze.4

Other crawlers (and I include crawlers for AI training data in this category) don't get the royal treatment. Most webmasters block other crawlers at the robots.txt level, by enforcing IP-based bans from the most common data center IP addresses, or by instituting more sophisticated fingerprinting to try and detect human presence. If you've ever tried to build a crawler before, you'll notice that you get rate limited or blocked far before Google crawlers ever would. The 66.249.x.x CIDR block really is a special gem.

Search engines might have the data advantage, but right now they're still training their models like everyone else. They have a batch training job that lasts for weeks or months, then they release the model. They'll repeat the exercise a few months later with new data and perhaps a new architecture. They're not actually leveraging their continuous crawling advantage in model development.

RAG Retrieval

There is a camp of ML researchers that believe RAG (retrieve-augment-generate) is the right abstraction to solve this problem. RAG introduces a conceptual framework of figuring out what users are looking for, then presenting this data to the LLM alongside the original user query. You can independently update the index without having to update the model itself.

Most of this pipeline looks more similar to a classic information retrieval system than to a modern LLM. It specifically combines an upfront pre-processing workflow and an inference workflow.

Upfront:

  • Map your dataset (in this case a crawl of the Internet) into datapoints of raw text.
  • Embed this text into an embedding space that captures its core meaning, or different embeddings that capture different questions that the page might answer.
  • Save these embeddings in an embedding store that's fast to query with a nearest-neighbor search.

Inference:

  • The user comes to a chatbot with a question.
  • Generate relevant search queries for this question. These queries could be phrases or they could be whole sentences. They can also be generated by an supplementary LLM or algorithmically via tf-idf or bm25.
  • Embed these search queries into the same embedding space as the documents that were indexed above.
  • Retrieve the top k (typically 5-15) documents from the index and inject these into a prompt.
  • Rely on the LLM to leverage the contextual data that is relevant, or ignore it if it's not helpful to answer the user's query.

As context windows get longer, we can fit more documents into the prompt. This allows the model to directly attend to the source content and potentially cite the content verbatim. This is in contrast to the core model weights that are baked into the architecture. They're both uninterpretable and have a fuzzier sense of knowledge; they usually can't verbatim cite their original training data.5

RAG is only as good as your embedding space, however. You have to be sure the right documents are retrieved to help the model answer the question. Otherwise it risks confusing the generation more than it aids the answer.

Stream-Based Training

I went to a lecture once from a tech lead on the Google speech-to-text project. He mentioned that Google received enough training data each day (either through in-house recording or through user submitted samples) that they were able to train their models in a continuous loop. Train the base model as a bulk job, then progressively fine-tune every day.

  1. Even there, there can be some large additions from one minor vesion to the next especially in batteries-included languages like Python. ↩

  2. Currently finetuned on 2023 data. Originally it was locked to a crawl completed in 2021. ↩

  3. Once something in CS is figured out the first time, it's always quick to figure out the second. ↩

  4. NYT, I'm looking over at you. ↩

  5. Although there is some evidence of the contrary. ↩