Gemini,本地且免费,使用 Chrome 与 Angular
Source: Dev.to
可用的 API
- Language API – 检测给定文本的语言。
- Translation API – 将文本从一种语言翻译成另一种语言。
- Prompt API – 接受自由形式的提示以生成结构化输出。
- Summarization API – 将长文本压缩为简洁的摘要。
在本文中,我将展示如何利用这些 API 添加真正有用的功能,而无需为 token 付费。
我觉得特别有趣的一点是,Google 搜索现在经常会给出 AI 生成的摘要,甚至直接给出答案。有时你只想要要点,而不是整篇文章。这个想法正是我们将在这里复现的内容。
Google 搜索摘要功能
目标: 构建一段小逻辑,为博客文章生成 TL;DR(太长不看)要点列表,让读者能够瞬间了解文章内容。
入门
-
更新 Chrome – 确保您使用的是最新版本。旧版本可能不包含最新的本地模型。
-
启用所需的标志 并重新启动 Chrome:
chrome://flags/#optimization-guide-on-device-model chrome://flags/#prompt-api-for-gemini-nano-multimodal-input -
安装模型,在控制台(或能够访问 Chrome API 的脚本)中运行以下代码:
const session = await LanguageModel.create({ monitor(m) { m.addEventListener('downloadprogress', (e) => { console.log(`Downloaded ${e.loaded * 100}%`); }); }, }); const summarizer = await Summarizer.create({ monitor(m) { m.addEventListener('downloadprogress', (e) => { console.log(`Downloaded ${e.loaded * 100}%`); }); }, });当下载达到 100 % 时,即可使用这些 API。
实现
我们将使用 Angular 来实现。如果你还没有安装好环境:
# 安装 Angular CLI
npm install -g @angular/cli
# 创建一个新项目(将 <name> 替换为你想要的名称)
ng new <name>
UI 提示(用于 Antigravity IDE)
下面是我们输入到 Google 新 IDE Antigravity 中以生成 UI 组件的提示:
You are an expert Frontend Developer. Your task is to build a premium, visually stunning blog post page for an Angular application. The project is already initialized.
### Goal
Create a standalone component named `BlogPost` that serves as a static blog post page. The design should be modern, "dark mode" by default, and evoke a high‑tech, futuristic feel suitable for the topic of "Agentic AI".
### Structure & Content Constraints
The page must contain the following specific elements, stacked vertically:
1. **Header Section**
- **Tags**: A row of small pill‑shaped tags: "Artificial Intelligence", "Future", "Tech".
- **Title**: Large, impactful typography: "The Rise of Agentic AI: A New Era of Coding".
- **Subtitle**: A lighter sub‑heading: "How autonomous agents are transforming the software development landscape".
2. **TL;DR Section**
- Placed prominently below the header but before the main content.
- Must clearly stand out (e.g., border, different background tint, or accent color).
- **Heading**: "TL;DR".
- **Content**: A bulleted list summarizing the article (e.g., AI moving from autocomplete to autonomy, changing developer roles to architects).
3. **Main Content**
- Several paragraphs discussing "Agentic AI".
- Explain how it differs from traditional coding assistants.
- Discuss the shift from "writing code" to "guiding agents".
- Use highly readable typography with good line height and contrast.
### Design & Aesthetics (Crucial)
- **Theme**: Dark mode. Background very dark (nearly black), text light grey/white.
- **Typography**: Clean sans‑serif font like *Inter*.
- **Color Palette**: Neon/electric accents.
- *Primary Accent*: Electric teal or cyan (for tags/highlights).
- *Secondary Accent*: Electric purple (for the TL;DR section or links).
- **Visual Style**:
- Blog post container looks like a "card" floating in the center with subtle shadow and rounded corners.
- Subtle gradients for the title if possible.
- Fully responsive (mobile‑friendly).
### Technical Requirements
- Use Angular **Standalone Components**.
- Hardcode all text directly in the template or component class.
- **Do NOT** implement any actual AI calls or backend services; this is purely a UI implementation task.
生成的 UI Mockup
此时,重点纯粹在 UI 上。尚未涉及任何 AI 调用。
实现 API
创建一个新的 Angular 服务来封装设备上的 API。下面是一个干净的起始模板:
import { Injectable } from '@angular/core';
// Types for the Chrome on‑device APIs (replace with actual typings if available)
declare const LanguageModel: any;
declare const Summarizer: any;
@Injectable({
providedIn: 'root',
})
export class OnDeviceAiService {
private languageModel: any;
private summarizer: any;
constructor() {
this.initModels();
}
/** Load the on‑device models */
private async initModels(): Promise {
this.languageModel = await LanguageModel.create({
monitor: (m: any) => {
m.addEventListener('downloadprogress', (e: any) => {
console.log(`Language model download: ${e.loaded * 100}%`);
});
},
});
this.summarizer = await Summarizer.create({
monitor: (m: any) => {
m.addEventListener('downloadprogress', (e: any) => {
console.log(`Summarizer download: ${e.loaded * 100}%`);
});
},
});
}
/** Detect language of a string */
async detectLanguage(text: string): Promise {
if (!this.languageModel) {
await this.initModels();
}
return this.languageModel.detectLanguage(text);
}
/** Summarize a block of text */
async summarize(text: string): Promise {
if (!this.summarizer) {
await this.initModels();
}
return this.summarizer.summarize(text);
}
}
现在可以在任何组件(例如 BlogPost 组件)中注入 OnDeviceAiService,并调用 summarize() 来生成 TL;DR 项目符号列表。
接下来的步骤
- 将服务接入
BlogPost组件,并在 TL;DR 区域显示生成的项目符号。 - 添加错误处理,以应对模型加载失败的情况。
- 尝试使用 Prompt API,获取更结构化的输出(例如 JSON 格式的摘要)。
就这样!你已经拥有一个零成本、在设备上运行的 AI 流程,能够在不消耗 token 预算的情况下为你的 Web 应用增添智能功能。祝编码愉快!
使用 Chrome 的 Summarizer 与 Prompt API 实现 AI 驱动的 TL;DR 生成
以下是一份完整、整理后的指南,教你如何创建一个服务,从文章中提取关键点并在 Angular 组件中以 TL;DR 列表的形式呈现。代码使用 Chrome 的 Summarizer API(稳定版)和 Prompt API(实验版)——均在本地运行,无需消耗 token 或产生费用。
1. 创建 Summarizer 会话
Summarizer 用于从文本中提取最重要的要点。
private async createSummarizerSession() {
return await Summarizer.create({
type: 'key-points', // 决定摘要的风格
length: 'short', // 简短摘要
expectedInputLanguages: ['en'], // 输入语言
outputLanguage: 'en', // 输出语言
expectedContextLanguages: ['en'],
sharedContext: 'About AI and Agentic AI'
});
}
注意:
type字段决定了摘要的生成方式。

完整选项列表请参见官方文档。
2. 创建 Prompt(语言模型)会话
我们将使用 Prompt API 将原始要点转换为干净的 HTML。
private async createLanguageModelSession() {
return await LanguageModel.create({
initialPrompts: [
{
role: 'system',
content: 'Convert these bullets into HTML. Return only the HTML.'
}
],
});
}
3. 合并两个会话
下面的函数将所有步骤串联起来:
async generateTlDr(content: string): Promise {
// 1️⃣ 对文章进行摘要
const summarizer = await this.createSummarizerSession();
const summary = await summarizer.summarize(content, {
context: 'This article is intended for a tech‑savvy audience.',
});
summarizer.destroy();
// 2️⃣ 将摘要转换为结构化输出
const lm = await this.createLanguageModelSession();
const result = await lm.prompt(summary, { responseConstraint: schema });
lm.destroy();
// 3️⃣ 解析 JSON 响应
const parsed = JSON.parse(result);
return parsed?.items ?? [];
}
schema(后文会展示)强制 Prompt API 返回一个包含 "bullet_list" 类型和 items 字符串数组的 JSON 对象。
4. 完整服务代码
import { Injectable } from '@angular/core';
declare const Summarizer: any;
declare const LanguageModel: any;
const schema = {
type: 'object',
required: ['type', 'items'],
properties: {
type: {
type: 'string',
enum: ['bullet_list'],
description: 'Identifies the content as a bullet list'
},
items: {
type: 'array',
minItems: 1,
items: {
type: 'string',
minLength: 1
},
description: 'Each entry is one bullet item, without bullet symbols'
}
},
additionalProperties: false
};
@Injectable({
providedIn: 'root'
})
export class AiService {
async generateTlDr(content: string): Promise {
const summarizer = await this.createSummarizerSession();
const summary = await summarizer.summarize(content, {
context: 'This article is intended for a tech‑savvy audience.',
});
summarizer.destroy();
const lm = await this.createLanguageModelSession();
const result = await lm.prompt(summary, { responseConstraint: schema });
lm.destroy();
const parsed = JSON.parse(result);
return parsed?.items ?? [];
}
private async createSummarizerSession() {
return await Summarizer.create({
type: 'key-points',
length: 'short',
expectedInputLanguages: ['en'],
outputLanguage: 'en',
expectedContextLanguages: ['en'],
sharedContext: 'About AI and Agentic AI'
});
}
private async createLanguageModelSession() {
return await LanguageModel.create({
initialPrompts:
Source: …
At this point the heavy lifting is done.
5. 将服务接入组件
组件 TypeScript
import { Component, inject, OnInit, signal } from '@angular/core';
import { AiService } from './ai.service';
@Component({
selector: 'app-post',
templateUrl: './post.component.html',
styleUrls: ['./post.component.scss']
})
export class PostComponent implements OnInit {
private aiService = inject(AiService);
public readonly postContent = content; // ([]);
async ngOnInit() {
const tldr = await this.aiService.generateTlDr(this.postContent);
this.tltrContent.set(tldr);
}
}
组件模板 (post.component.html)
<h3>TL;DR</h3>
@if (tltrContent().length > 0) {
<ul>
@for (item of tltrContent(); track $index) {
<li>{{ item }}</li>
}
</ul>
} @else {
Loading...
}
TL;DR 列表将在本地 AI 完成处理后渲染。
6. 结果预览
以下是完全在设备上生成的真实示例(无外部令牌,无费用)。

7. 支持与稳定性
| API | 稳定性 | 在本示例中的作用 |
|---|---|---|
| Summarizer API | 稳定 | 生成要点摘要 |
| Prompt API | 实验性 | 将项目符号格式化为 HTML(或 JSON) |

