引言
随着人工智能技术的快速发展,将 AI 能力集成到现代 Web 应用程序中已成为提升用户体验的重要方式。Genkit 作为一个强大的 AI 开发工具包,为开发者提供了便捷的方式来构建和集成 AI 功能。本文将详细介绍如何在 Angular 应用程序中使用 Genkit 流(flows),从项目创建、依赖安装到流定义和前后端交互的全过程。
Angular 作为主流的前端框架之一,结合 Genkit 可以轻松实现 AI 功能的集成。本文将通过一个餐厅菜单建议的具体示例,展示如何在 Angular 应用中实现非流式和流式两种调用方式,帮助开发者快速掌握这一技术组合。
正文
准备工作与环境配置
熟悉 Genkit 流概念
在开始之前,开发者需要熟悉 Genkit 的核心概念------流(flows)。Genkit 流是一种封装 AI 功能的可重用单元,可以接受输入、处理请求并返回输出。理解如何编写和调用 Genkit 流是成功集成的关键。
创建 Angular 项目
为了演示 Genkit 在 Angular 中的使用,我们需要一个支持服务器端渲染(SSR)和服务器路由的 Angular 项目。可以使用 Angular CLI 快速创建这样的项目:
bash
ng new --ssr --server-routing
如果已有现有项目,可以通过以下命令添加服务器端路由支持:
bash
ng add @angular/ssr --server-routing
这两种方式都能确保我们的应用具备必要的服务器端功能,以便处理 Genkit 流的 API 请求。
安装 Genkit 依赖
在 Angular 项目中安装必要的 Genkit 依赖项是下一步。首先安装核心 Genkit 库:
bash
npm install genkit
接着安装至少一个模型插件,例如 Google 的 Gemini 模型:
bash
npm install @genkit-ai/googleai
还需要安装 Genkit Express 库,以便在服务器端处理流请求:
bash
npm install @genkit-ai/express
虽然可选,但建议全局安装 Genkit CLI 和 tsx 工具,以便开发和测试:
bash
npm install -g genkit-cli
npm install --save-dev tsx
这些工具将大大简化开发流程,特别是在测试和调试 Genkit 流时。
定义 Genkit 流
创建流目录结构
在 Angular 项目中创建一个专门的目录来存放 Genkit 流定义是一个好习惯。建议在 src
下创建 genkit
目录:
css
src/
genkit/
menuSuggestionFlow.ts
这种结构保持了项目的整洁性,便于管理和维护多个流定义。
编写菜单建议流
下面是一个具体的菜单建议流实现示例。这个流接受一个餐厅主题作为输入,返回一个符合该主题的菜单项建议:
typescript
import { googleAI } from '@genkit-ai/googleai';
import { genkit, z } from 'genkit';
const ai = genkit({
plugins: [googleAI()],
});
export const menuSuggestionFlow = ai.defineFlow(
{
name: 'menuSuggestionFlow',
inputSchema: z.object({ theme: z.string() }),
outputSchema: z.object({ menuItem: z.string() }),
streamSchema: z.string(),
},
async ({ theme }, { sendChunk }) => {
const { stream, response } = ai.generateStream({
model: googleAI.model('gemini-2.5-flash'),
prompt: `Invent a menu item for a ${theme} themed restaurant.`,
});
for await (const chunk of stream) {
sendChunk(chunk.text);
}
const { text } = await response;
return { menuItem: text };
}
);
这个流定义展示了几个关键点:
- 使用 Zod 定义输入输出模式,确保类型安全
- 集成 Google 的 Gemini 模型进行文本生成
- 支持流式传输,可以实时返回部分结果
- 最终返回完整的菜单项建议
这种模式可以轻松扩展到其他类似的 AI 功能实现。
服务器端配置
添加 Express 路由
要在 Angular 应用中暴露 Genkit 流,需要在服务器端配置相应的路由。修改 src/server.ts
文件:
首先添加必要的导入:
typescript
import { expressHandler } from '@genkit-ai/express';
import { menuSuggestionFlow } from './genkit/menuSuggestionFlow';
然后初始化 Express 应用并添加 JSON 解析中间件:
typescript
app.use(express.json());
最后添加流路由:
typescript
app.post('/api/menuSuggestion', expressHandler(menuSuggestionFlow));
这样配置后,前端就可以通过 /api/menuSuggestion
端点调用菜单建议流了。
前端调用实现
非流式调用实现
对于不需要实时更新的场景,可以使用非流式调用方式。修改 src/app/app.component.ts
:
typescript
import { Component, resource, signal } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { runFlow } from 'genkit/beta/client';
@Component({
selector: 'app-root',
imports: [FormsModule],
templateUrl: './app.component.html',
})
export class AppComponent {
menuInput = '';
theme = signal('');
menuResource = resource({
request: () => this.theme(),
loader: ({ request }) => runFlow({
url: 'http://localhost:4200/api/menuSuggestion',
input: { theme: request }
}),
});
}
对应的模板 (app.component.html
) 实现:
html
<main>
<h3>Generate a custom menu item</h3>
<label for="theme">Suggest a menu item for a restaurant with this theme: </label>
<input type="text" id="theme" [(ngModel)]="menuInput" />
<button (click)="theme.set(menuInput)">Generate</button>
<br />
<br />
@if (menuResource.isLoading()) {
<div>Loading...</div>
} @else if (menuResource.value()) {
<div>
<h4>Generated Menu Item:</h4>
<pre>{{ menuResource.value().menuItem }}</pre>
</div>
}
</main>
这种实现简单直接,适合大多数基础场景。
流式调用实现
对于需要实时显示生成过程的场景,流式调用提供了更好的用户体验。扩展组件以支持流式响应:
typescript
import { Component, resource, signal } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { runFlow, streamFlow } from 'genkit/beta/client';
@Component({
selector: 'app-root',
imports: [FormsModule],
templateUrl: './app.component.html',
})
export class AppComponent {
menuInput = '';
theme = signal('');
streamedText = signal('');
isStreaming = signal(false);
menuResource = resource({
request: () => this.theme(),
loader: ({ request }) => runFlow({
url: 'http://localhost:4200/api/menuSuggestion',
input: { theme: request }
}),
});
async streamMenuItem() {
const theme = this.menuInput;
if (!theme) return;
this.isStreaming.set(true);
this.streamedText.set('');
try {
const result = streamFlow({
url: 'http://localhost:4200/api/menuSuggestion',
input: { theme },
});
for await (const chunk of result.stream) {
this.streamedText.update(prev => prev + chunk);
}
const finalOutput = await result.output;
console.log('Final output:', finalOutput);
} catch (error) {
console.error('Error streaming menu item:', error);
} finally {
this.isStreaming.set(false);
}
}
}
更新模板以支持流式显示:
html
<main>
<h3>Generate a custom menu item</h3>
<label for="theme">Suggest a menu item for a restaurant with this theme: </label>
<input type="text" id="theme" [(ngModel)]="menuInput" />
<br />
<br />
<button (click)="theme.set(menuInput)" [disabled]="menuResource.isLoading()">
Generate
</button>
<button (click)="streamMenuItem()" [disabled]="isStreaming()">
Stream Generation
</button>
<br />
@if (streamedText()) {
<div>
<h4>Streaming Output:</h4>
<pre>{{ streamedText() }}</pre>
</div>
}
@if (menuResource.isLoading()) {
<div>Loading...</div>
} @else if (menuResource.value()) {
<div>
<h4>Generated Menu Item:</h4>
<pre>{{ menuResource.value().menuItem }}</pre>
</div>
}
@if (isStreaming()) {
<div>Streaming...</div>
}
</main>
流式实现提供了更动态的用户体验,特别适合生成较长内容或需要实时反馈的场景。
高级配置选项
身份验证集成
在实际应用中,通常需要为 API 路由添加身份验证。Genkit 支持通过请求头传递认证令牌:
typescript
menuResource = resource({
request: () => this.theme(),
loader: ({ request }) => runFlow({
url: 'http://localhost:4200/api/menuSuggestion',
headers: {
Authorization: 'Bearer your-token-here',
},
input: { theme: request }
}),
});
这种机制可以灵活地集成各种认证方案,如 JWT、OAuth 等,确保 API 调用的安全性。
本地测试与调试
在本地开发环境中运行应用时,需要为所使用的模型 API 服务配置凭据。例如,对于 Gemini API:
bash
export GEMINI_API_KEY=<your API key>
然后正常启动应用:
bash
ng serve
Genkit 的开发工具也可以正常使用,例如启动开发者 UI 来测试流:
bash
genkit start -- npx tsx --watch src/genkit/menuSuggestionFlow.ts
这些工具大大简化了开发流程,使得测试和调试 Genkit 流变得更加高效。
结论
本文详细介绍了在 Angular 应用程序中集成 Genkit 的完整流程。从项目创建、依赖安装到流定义和前后端交互,我们通过一个具体的菜单建议示例展示了两种调用方式:传统的非流式调用和更先进的流式调用。
关键要点包括:
- Genkit 流提供了一种结构化的方式来封装 AI 功能
- Angular 与 Genkit 的集成需要适当的服务器端配置
- 流式调用可以实现更动态的用户体验
- 身份验证和本地测试工具保证了开发的安全性和便捷性
这种技术组合为开发者提供了强大的工具,可以轻松地将 AI 能力集成到 Angular 应用中,创造更智能、更交互式的用户体验。随着 AI 技术的不断发展,这种集成模式将在现代 Web 开发中扮演越来越重要的角色。