Di chuyển từ phiên bản 0.5

Genkit 0.9 giới thiệu một số thay đổi có thể gây lỗi cùng với các tính năng nâng cao giúp cải thiện chức năng tổng thể. Nếu đang phát triển ứng dụng bằng Genkit 0.5, bạn sẽ cần cập nhật mã ứng dụng khi nâng cấp lên phiên bản mới nhất. Hướng dẫn này trình bày những thay đổi quan trọng nhất và đưa ra các bước để di chuyển ứng dụng hiện có một cách suôn sẻ.

Hướng dẫn bắt đầu nhanh

Các bước sau đây sẽ giúp bạn nhanh chóng di chuyển từ Genkit 0.5 sang Genkit 0.9. Hãy đọc thêm thông tin về những thay đổi này trong Nhật ký thay đổi chi tiết bên dưới.

1. Cài đặt CLI mới

  • Gỡ cài đặt CLI cũ

    npm uninstall -g genkit && npm uninstall genkit
    
  • Cài đặt CLI mới

    npm i -D genkit-cli
    

2. Cập nhật phần phụ thuộc

  • Xoá từng gói cốt lõi Genkit

    npm uninstall @genkit-ai/ai @genkit-ai/core @genkit-ai/dotprompt @genkit-ai/flow
    
  • Cài đặt gói genkit tổng hợp mới

    npm i --save genkit
    
  • Nâng cấp tất cả phiên bản trình bổ trợ (ví dụ bên dưới)

    npm upgrade @genkit-ai/firebase
    

3. Thay đổi các lệnh nhập

  • Xoá các lệnh nhập cho từng gói cốt lõi Genkit

    import { … } from '@genkit-ai/ai';
    import { … } from '@genkit-ai/core';
    import { … } from '@genkit-ai/flow';
    
  • Xoá các lệnh nhập zod

    import * as z from 'zod';
    
  • Nhập genkitzod từ genkit

    import { z, genkit } from 'genkit';
    

4. Cập nhật mã

Xoá các khối configureGenkit

Cấu hình cho Genkit hiện được thực hiện cho mỗi thực thể. Dữ liệu đo từ xa và ghi nhật ký được định cấu hình trên toàn hệ thống và riêng biệt với thực thể Genkit.

  • Thay thế configureGenkit bằng các khối ai = genkit({...}). Chỉ giữ lại cấu hình trình bổ trợ.

    import { genkit } from 'genkit';
    
    const ai = genkit({ plugins: [...]});
    
  • Định cấu hình dữ liệu đo từ xa bằng cách sử dụng enableFirebaseTelemetry hoặc enableGoogleCloudTelemetry

    Đối với Firebase:

    import { enableFirebaseTelemetry } from '@genkit-ai/firebase';
    
    enableFirebaseTelemetry({...});
    

    Đối với Google Cloud:

    import { enableGoogleCloudTelemetry } from '@genkit-ai/google-cloud';
    
    enableGoogleCloudTelemetry({...});
    
  • Thiết lập cấp độ ghi nhật ký một cách độc lập ```js import { logger } from 'genkit/logging';

    logger.setLogLevel('debug'); ```

Hãy xem tài liệu về Theo dõi và ghi nhật ký để biết thêm thông tin chi tiết về cách định cấu hình tính năng đo từ xa và ghi nhật ký.

Hãy xem tài liệu Bắt đầu để biết thêm thông tin chi tiết về cách định cấu hình một thực thể Genkit.

Di chuyển các thao tác Genkit để được gọi từ thực thể genkit

Các hành động (luồng, công cụ, trình truy xuất, trình lập chỉ mục, v.v.) được xác định theo từng thực thể. Hãy đọc Nhật ký thay đổi để biết tất cả các tính năng mà bạn cần thay đổi, nhưng sau đây là ví dụ về một số tính năng phổ biến.

import { genkit } from 'genkit';
import { onFlow } from '@genkit-ai/firebase/functions';

const ai = genkit({ plugins: [...]});

// Flows and tools are defined on the specific genkit instance
// and are directly callable.
const sampleFlow = ai.defineFlow(...);
const sampleTool = ai.defineTool(...);

async function callMyFlow() {
  // Previously, text output could accessed via .text()
  // Now it is either .output() or .text
  return await sampleFlow().output();
}

// onFlow now takes the Genkit instance as first argument
// This registers the flow as a callable firebase function
onFlow(ai, ...);
const flows = [ sampleFlow, ... ];
// Start the flow server to make the registered flows callable over HTTP
ai.startFlowServer({flows});

5. Chạy ứng dụng

# run the DevUI and your js code
genkit start -- <command to run node>
# run a defined flow
genkit flow:run <flowName>

Nhật ký thay đổi

1. Thay đổi về CLI

Giao diện dòng lệnh (CLI) đã trải qua những thay đổi đáng kể trong Genkit 0.9. Lệnh để khởi động Genkit đã thay đổi và CLI đã được tách thành gói độc lập riêng. Giờ đây, bạn cần cài đặt riêng CLI.

Cách cài đặt CLI:

npm i -g genkit-cli

Một số thay đổi đã được thực hiện đối với lệnh genkit start:

Khởi động mã ứng dụng Genkit + Giao diện người dùng dành cho nhà phát triển cùng nhau:

genkit start -- [start command]
genkit start -- tsx src/index.ts
genkit start -- go run main.go

Chế độ xem cũng được hỗ trợ:

genkit start -- tsx --watch src/index.ts

CHỈ khởi động mã ứng dụng của bạn ở chế độ phát triển Genkit:

genkit start --noui -- <start command>
genkit start --noui -- tsx src/index.ts

CHỈ bắt đầu giao diện người dùng dành cho nhà phát triển:

genkit start

Trước đây, lệnh genkit start sẽ khởi động cùng lúc Giao diện người dùng dành cho nhà phát triển và mã ứng dụng. Nếu có quy trình CI/CD nào dựa vào lệnh này, bạn có thể cần cập nhật quy trình đó.

Giao diện người dùng dành cho nhà phát triển sẽ tương tác trực tiếp với máy chủ flow để tìm hiểu những flow nào đã được đăng ký và cho phép bạn gọi trực tiếp các flow đó bằng dữ liệu đầu vào mẫu.

2. Đơn giản hoá các gói và lệnh nhập

Trước đây, các thư viện Genkit được tách thành một số mô-đun mà bạn cần cài đặt và nhập riêng lẻ. Các mô-đun này hiện đã được hợp nhất thành một lệnh nhập duy nhất. Ngoài ra, mô-đun Zod hiện được Genkit xuất lại.

Cũ:

npm i @genkit-ai/core @genkit-ai/ai @genkit-ai/flow @genkit-ai/dotprompt

Mới:

npm i genkit

Cũ:

import { … } from '@genkit-ai/ai';
import { … } from '@genkit-ai/core';
import { … } from '@genkit-ai/flow';
import * as z from 'zod';

Mới:

import { genkit, z } from 'genkit';

Bạn vẫn phải cài đặt và nhập từng trình bổ trợ Genkit.

3. Định cấu hình Genkit

Trước đây, việc khởi chạy Genkit được thực hiện một lần trên toàn cục bằng cách gọi hàm configureGenkit. Tất cả tài nguyên Genkit (luồng, công cụ, lời nhắc, v.v.) đều sẽ tự động được kết nối với cấu hình chung này.

Genkit 0.9 giới thiệu các thực thể Genkit, mỗi thực thể đóng gói một cấu hình. Hãy xem các ví dụ sau:

Cũ:

import { configureGenkit } from '@genkit-ai/core';

configureGenkit({
  telemetry: {
    instrumentation: ...,
    logger: ...
  }
});

Mới:

import { genkit } from 'genkit';
import { logger } from 'genkit/logging';
import { enableFirebaseTelemetry } from '@genkit-ai/firebase';

logger.setLogLevel('debug');
enableFirebaseTelemetry({...});

const ai = genkit({ ... });

Hãy cùng phân tích:

  • configureGenkit() đã được thay thế bằng genkit() và trả về một thực thể Genkit đã định cấu hình thay vì thiết lập cấu hình trên toàn cục.
  • Hàm khởi chạy Genkit hiện nằm trong gói genkit.
  • Tính năng ghi nhật ký và đo từ xa vẫn được định cấu hình trên toàn cầu bằng các phương thức rõ ràng của riêng chúng. Các cấu hình này áp dụng đồng nhất cho tất cả các thực thể Genkit.

4. Xác định luồng và khởi động máy chủ luồng một cách rõ ràng

Giờ đây, khi đã định cấu hình một thực thể Genkit, bạn cần xác định các luồng của mình. Tất cả các phương thức API cốt lõi dành cho nhà phát triển như defineFlow, defineToolonFlow hiện được gọi thông qua thực thể này.

Điều này khác với cách trước đây, trong đó các luồng và công cụ được đăng ký trên toàn cầu.

Cũ:

import { defineFlow, defineTool, onFlow } from '@genkit-ai/core';

defineFlow(...);
defineTool(...);

onFlow(...);

Mới:

// Define tools and flows
const sampleFlow = ai.defineFlow(...);
const sampleTool = ai.defineTool(...);

// onFlow now takes the Genkit instance as first argument
// This registers the flow as a callable firebase function
onFlow(ai, ...);  

const flows = [ sampleFlow, ... ];
// Start the flow server to make the registered flows callable over HTTP
ai.startFlowServer({flows});

Hiện tại, tất cả các flow mà bạn muốn cung cấp đều cần được đăng ký rõ ràng trong mảng flows ở trên.

5. Công cụ và câu lệnh phải được xác định tĩnh

Trong các phiên bản Genkit trước, bạn có thể xác định linh động các công cụ và lời nhắc trong thời gian chạy, ngay trong luồng.

Trong Genkit 0.9, hành vi này không còn được phép. Thay vào đó, bạn cần xác định tất cả các hành động và luồng bên ngoài quá trình thực thi luồng (tức là tĩnh).

Thay đổi này thực thi việc phân tách nghiêm ngặt hơn giữa các định nghĩa hành động và quá trình thực thi.

Nếu có bất kỳ mã nào được xác định một cách linh động, bạn cần phải tái cấu trúc các mã đó. Nếu không, lỗi sẽ được gửi trong thời gian chạy khi luồng được thực thi.

❌ KHÔNG NÊN:

const flow = defineFlow({...}, async (input) => {
  const tool = defineTool({...});
  await tool(...);
});

✅ NÊN:

const tool = ai.defineTool({...});

const flow = ai.defineFlow({...}, async (input) => {
  await tool(...);
});

6. API mới cho luồng truyền trực tuyến

Trong Genkit 0.9, chúng tôi đã đơn giản hoá cú pháp để xác định luồng truyền trực tuyến và gọi luồng đó.

Trước tiên, defineFlowdefineStreamingFlow đã được tách riêng. Nếu có luồng cần truyền trực tuyến, bạn sẽ phải cập nhật mã để xác định luồng đó thông qua defineStreamingFlow.

Thứ hai, thay vì gọi các hàm stream()response() riêng biệt, cả luồng và phản hồi hiện là các giá trị được trả về trực tiếp từ luồng. Thay đổi này giúp đơn giản hoá việc truyền trực tuyến luồng.

Cũ:

import { defineFlow, streamFlow } from '@genkit-ai/flow';

const myStreamingFlow = defineFlow(...);
const { stream, output } = await streamFlow(myStreamingFlow, ...);

for await (const chunk of stream()) {
  console.log(chunk);
}

console.log(await output());

Mới:

const myStreamingFlow = ai.defineStreamingFlow(...);
const { stream, response } = await myStreamingFlow(...);

for await (const chunk of stream) {
  console.log(chunk);
}

console.log(await response);

7. Thay thế các phương thức lớp GenerateResponse bằng các thuộc tính getter

Trước đây, bạn thường truy cập vào văn bản hoặc kết quả có cấu trúc của phản hồi bằng cách sử dụng các phương thức lớp, chẳng hạn như output() hoặc text().

Trong Genkit 0.9, các phương thức đó đã được thay thế bằng thuộc tính getter. Điều này giúp đơn giản hoá việc xử lý các phản hồi.

Cũ:

const response = await generate({ prompt: 'hi' });
console.log(response.text());

Mới:

const response = await ai.generate('hi');
console.log(response.text);

Điều tương tự cũng áp dụng cho output:

Cũ:

console.log(response.output());

Mới:

console.log(response.output);

8. Loại bỏ tính năng tạo đề xuất

Genkit 0.9 đơn giản hoá việc xử lý phản hồi bằng cách xoá thuộc tính candidates. Trước đây, các phản hồi có thể chứa nhiều đề xuất mà bạn cần xử lý một cách rõ ràng. Giờ đây, chỉ đề xuất đầu tiên được trả về trực tiếp trong một phản hồi phẳng.

Mọi mã truy cập trực tiếp vào các đề xuất sẽ không hoạt động nữa.

Cũ:

const response = await generate({
 messages: [ { role: 'user', content: ...} ]
});
console.log(response.candidates); // previously you could access candidates directly

Mới:

const response = await ai.generate({
 messages: [ { role: 'user', content: ...} ]
});
console.log(response.message); // single candidate is returned directly in a flat response

9. Tạo API – Các tính năng nâng cao cho nhiều lượt

Đối với các cuộc trò chuyện nhiều lượt, phương thức toHistory() cũ đã được thay thế bằng messages, giúp đơn giản hoá thêm cách xử lý nhật ký cuộc trò chuyện.

Cũ:

const history = response.toHistory();

Mới:

const response = await ai.generate({
 messages: [ { role: 'user', content: ...} ]
});
const history = response.messages;

10. Chat API tinh giản

Trong Genkit 0.9, Chat API đã được thiết kế lại để dễ dàng quản lý và tương tác với phiên hơn. Dưới đây là cách bạn có thể tận dụng tính năng này cho cả trải nghiệm trò chuyện đồng bộ và trò chuyện trực tuyến:

import { genkit } from 'genkit';
import { gemini15Flash, googleAI } from '@genkit-ai/googleai';

const ai = genkit({
 plugins: [googleAI()],
 model: gemini15Flash,
});

const session = ai.createSession({ store: firestoreSessionStore() });
const chat = await session.chat({ system: 'talk like a pirate' });

let response = await chat.send('hi, my name is Pavel');
console.log(response.text()); // "hi Pavel, I'm llm"

// continue the conversation
response = await chat.send("what's my name");
console.log(response.text()); // "Pavel"

// can stream
const { response, stream } = await chat.sendStream('bye');
for await (const chunk of stream) {
 console.log(chunk.text());
}
console.log((await response).text());

// can load session from the store
const prevSession = await ai.loadSession(session.id, { store });
const prevChat = await prevSession.chat();
await prevChat.send('bye');