Stories

Detail Return Return

在 Angular 應用程序中使用 Genkit 的完整指南 - Stories Detail

引言

隨着人工智能技術的快速發展,將 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 快速創建這樣的項目:

ng new --ssr --server-routing

如果已有現有項目,可以通過以下命令添加服務器端路由支持:

ng add @angular/ssr --server-routing

這兩種方式都能確保我們的應用具備必要的服務器端功能,以便處理 Genkit 流的 API 請求。

安裝 Genkit 依賴

在 Angular 項目中安裝必要的 Genkit 依賴項是下一步。首先安裝核心 Genkit 庫:

npm install genkit

接着安裝至少一個模型插件,例如 Google 的 Gemini 模型:

npm install @genkit-ai/googleai

還需要安裝 Genkit Express 庫,以便在服務器端處理流請求:

npm install @genkit-ai/express

雖然可選,但建議全局安裝 Genkit CLI 和 tsx 工具,以便開發和測試:

npm install -g genkit-cli
npm install --save-dev tsx

這些工具將大大簡化開發流程,特別是在測試和調試 Genkit 流時。

定義 Genkit 流

創建流目錄結構

在 Angular 項目中創建一個專門的目錄來存放 Genkit 流定義是一個好習慣。建議在 src 下創建 genkit 目錄:

src/
  genkit/
    menuSuggestionFlow.ts

這種結構保持了項目的整潔性,便於管理和維護多個流定義。

編寫菜單建議流

下面是一個具體的菜單建議流實現示例。這個流接受一個餐廳主題作為輸入,返回一個符合該主題的菜單項建議:

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 };
  }
);

這個流定義展示了幾個關鍵點:

  1. 使用 Zod 定義輸入輸出模式,確保類型安全
  2. 集成 Google 的 Gemini 模型進行文本生成
  3. 支持流式傳輸,可以實時返回部分結果
  4. 最終返回完整的菜單項建議

這種模式可以輕鬆擴展到其他類似的 AI 功能實現。

服務器端配置

添加 Express 路由

要在 Angular 應用中暴露 Genkit 流,需要在服務器端配置相應的路由。修改 src/server.ts 文件:

首先添加必要的導入:

import { expressHandler } from '@genkit-ai/express';
import { menuSuggestionFlow } from './genkit/menuSuggestionFlow';

然後初始化 Express 應用並添加 JSON 解析中間件:

app.use(express.json());

最後添加流路由:

app.post('/api/menuSuggestion', expressHandler(menuSuggestionFlow));

這樣配置後,前端就可以通過 /api/menuSuggestion 端點調用菜單建議流了。

前端調用實現

非流式調用實現

對於不需要實時更新的場景,可以使用非流式調用方式。修改 src/app/app.component.ts

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) 實現:

<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>

這種實現簡單直接,適合大多數基礎場景。

流式調用實現

對於需要實時顯示生成過程的場景,流式調用提供了更好的用户體驗。擴展組件以支持流式響應:

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);
    }
  }
}

更新模板以支持流式顯示:

<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 支持通過請求頭傳遞認證令牌:

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:

export GEMINI_API_KEY=<your API key>

然後正常啓動應用:

ng serve

Genkit 的開發工具也可以正常使用,例如啓動開發者 UI 來測試流:

genkit start -- npx tsx --watch src/genkit/menuSuggestionFlow.ts

這些工具大大簡化了開發流程,使得測試和調試 Genkit 流變得更加高效。

結論

本文詳細介紹了在 Angular 應用程序中集成 Genkit 的完整流程。從項目創建、依賴安裝到流定義和前後端交互,我們通過一個具體的菜單建議示例展示了兩種調用方式:傳統的非流式調用和更先進的流式調用。

關鍵要點包括:

  1. Genkit 流提供了一種結構化的方式來封裝 AI 功能
  2. Angular 與 Genkit 的集成需要適當的服務器端配置
  3. 流式調用可以實現更動態的用户體驗
  4. 身份驗證和本地測試工具保證了開發的安全性和便捷性

這種技術組合為開發者提供了強大的工具,可以輕鬆地將 AI 能力集成到 Angular 應用中,創造更智能、更交互式的用户體驗。隨着 AI 技術的不斷髮展,這種集成模式將在現代 Web 開發中扮演越來越重要的角色。

user avatar u_15214399 Avatar donnytab Avatar kitty-38 Avatar laggage Avatar daishuyunshuzhanqianduan Avatar digitalocean Avatar writers Avatar liudamao Avatar zz_641473ad470bc Avatar daivon Avatar apachekylin Avatar xingfudenaozhong Avatar
Favorites 19 users favorite the story!
Favorites

Add a new Comments

Some HTML is okay.