Kesintileri kullanarak oluşturmayı duraklatma

Arama araları, kontrolü size geri vermek için LLM oluşturma ve araç çağırma döngüsünü duraklatabilen özel bir araç türüdür. Hazır olduğunuzda, LLM'nin daha fazla oluşturma işlemi için işleyeceği yanıtlar göndererek oluşturma işlemini devam ettirebilirsiniz.

Kesintiler için en yaygın kullanım alanları birkaç kategoriye ayrılır:

  • Döngüdeki insan: Etkileşimli yapay zekanın kullanıcısının, gerekli bilgileri netleştirmesini veya LLM'nin işlemi tamamlanmadan önce işlemi onaylamasını sağlayarak güvenlik ve güven sağlar.
  • Eşzamansız İşleme: İnsan inceleme uzmanına onay bildirimi gönderme veya uzun süre çalışan bir arka plan işlemini başlatma gibi yalnızca bant dışı olarak tamamlanabilen eşzamansız bir görev başlatma.
  • Bağımsız Görevden Çıkış: Uzun bir araç çağrısı dizisinde yineleme yapabilecek bir iş akışında, modele bir görevi tamamlandı olarak işaretlemesi için bir yol sağlamak.

Başlamadan önce

Burada açıklanan örneklerin tümü, Genkit bağımlılıkları yüklü bir proje oluşturduğunuzu varsaymaktadır. Bu sayfadaki kod örneklerini çalıştırmak istiyorsanız önce Başlangıç kılavuzundaki adımları tamamlayın.

Çok ayrıntılı incelemeye başlamadan önce aşağıdaki kavramlara da aşina olmanız gerekir:

Kesintilere genel bakış

Genel olarak, LLM ile etkileşimde bulunan bir kesinti şu şekilde görünür:

  1. Çağıran uygulama, LLM'ye bir istek gönderir. İstem, LLM'nin yanıt oluşturmak için kullanabileceği en az bir kesinti aracı da dahil olmak üzere bir araç listesi içerir.
  2. LLM, belirli bir biçimde tam bir yanıt veya araç çağrısı isteği oluşturur. LLM için kesinti çağrısı, diğer tüm araç çağrılarına benzer.
  3. LLM bir kesinti aracı çağırırsa Genkit kitaplığı, yanıtları ek işleme için hemen modele geri göndermek yerine oluşturmayı otomatik olarak duraklatır.
  4. Geliştirici, kesinti çağrısı yapılıp yapılmadığını kontrol eder ve kesinti yanıtı için gereken bilgileri toplamak üzere gereken görevi gerçekleştirir.
  5. Geliştirici, modele bir kesinti yanıtı göndererek oluşturmayı devam ettirir. Bu işlem, 2. Adım'a geri dönmenizi tetikler.

Manuel yanıt kesintilerini tanımlama

En yaygın kesinti türü, LLM'nin kullanıcıdan açıklama istemesine olanak tanır (ör. çoklu seçimli soru sorarak).

Bu kullanım alanı için Genkit örneğinin defineInterrupt() yöntemini kullanın:

import { genkit, z } from 'genkit';
import { googleAI, gemini15Flash } from '@genkitai/google-ai';

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

const askQuestion = ai.defineInterrupt({
  name: 'askQuestion',
  description: 'use this to ask the user a clarifying question',
  inputSchema: z.object({
    choices: z.array(z.string()).describe('the choices to display to the user'),
    allowOther: z.boolean().optional().describe('when true, allow write-ins')
  }),
  outputSchema: z.string()
});

Bir kesintinin outputSchema değerinin, bir araç işlevi tarafından otomatik olarak doldurulacak bir değer yerine sağlayacağınız yanıt verilerine karşılık geldiğini unutmayın.

Kesintileri kullanma

Diğer araç türlerinde olduğu gibi, içerik oluşturulurken kesintiler tools dizisine iletilir. Aynı generate çağrısına hem normal araçları hem de kesintileri iletebilirsiniz:

generate

const response = await ai.generate({
  prompt: 'Ask me a movie trivia question.',
  tools: [askQuestion],
});

definePrompt

const triviaPrompt = ai.definePrompt(
  {
    name: 'triviaPrompt',
    tools: [askQuestion],
    input: {
      schema: z.object({subject: z.string()})
    },
    prompt: 'Ask me a trivia question about {{subject}}
    .',
  }
);

const response = await triviaPrompt({ subject: 'computer history' });

İstem dosyası

---
tools: [askQuestion]
input:
  schema:
    partyType: string
---
{{role "system"}}
Use the askQuestion tool if you need to clarify something.

{{role "user"}}
Help me plan a {{partyType}} party next week.

Ardından, istemi kodunuzda aşağıdaki gibi yürütebilirsiniz:

```ts
// assuming prompt file is named partyPlanner.prompt
const partyPlanner = ai.prompt('partyPlanner');

const response = await partyPlanner({ partyType: 'birthday' });
```

Sohbet

const chat = ai.chat({
  system: 'Use the askQuestion tool if you need to clarify something.',
  tools: [askQuestion],
});

const response = await chat.send('make a plan for my birthday party');

Genkit, kesinti aracı çağrısı aldığında hemen bir yanıt döndürür.

Araya girmelere yanıt verme

Oluştur çağrınıza bir veya daha fazla kesinti aktardıysanız bunları işleyebilmek için kesintiler için yanıtı kontrol etmeniz gerekir:

// you can check the 'finishReason' of the response
response.finishReason === 'interrupted'
// or you can check to see if any interrupt requests are on the response
response.interrupts.length > 0

Kesintiye yanıt vermek için sonraki bir generate çağrısında resume seçeneği kullanılır. Bu durumda mevcut geçmişin iletildiğinden emin olun. Her araçta, yanıtın oluşturulmasına yardımcı olacak bir .respond() yöntemi bulunur.

Devam ettirildikten sonra model, tamamlanana veya başka bir kesinti tetiklenene kadar araç yürütme dahil olmak üzere oluşturma döngüsüne yeniden girer:

let response = await ai.generate({
  tools: [askQuestion],
  system: 'ask clarifying questions until you have a complete solution',
  prompt: 'help me plan a backyard BBQ',
});

while (response.interrupts.length) {
  const answers = [];
  // multiple interrupts can be called at once, so we handle them all
  for (const question in response.interrupts) {
    answers.push(
      // use the `respond` method on our tool to populate answers
      askQuestion.respond(
        question,
        // send the tool request input to the user to respond
        await askUser(question.toolRequest.input)
      )
    );
  }

  response = await ai.generate({
    tools: [askQuestion],
    messages: response.messages,
    resume: {
      respond: answers
    }
  })
}

// no more interrupts, we can see the final response
console.log(response.text);

Yeniden başlatılabilen kesintileri olan araçlar

Kesintiler için yaygın olan bir diğer kalıp da, LLM'nin önerdiği bir işlemi gerçekleştirmeden önce onaylama ihtiyacıdır. Örneğin, bir ödeme uygulaması kullanıcıdan belirli türde aktarımları onaylamasını isteyebilir.

Bu kullanım alanında, standart defineTool yöntemini kullanarak bir kesintinin ne zaman tetikleneceği ve kesinti yeniden başlatıldığında ne yapılacağıyla ilgili özel mantık eklemek için ek meta veriler kullanabilirsiniz.

Yeniden başlatılabilir bir araç tanımlama

Her araç, uygulama tanımının ikinci bağımsız değişkeninde iki özel yardımcıya erişebilir:

  • interrupt: Bu yöntem çağrıldığında, oluşturma döngüsünü duraklatmak için yakalanan özel bir istisna atar. Nesne olarak ek meta veriler sağlayabilirsiniz.
  • resumed: Kesintiye uğramış bir oluşturma isteği {resume: {restart: ...}} seçeneği kullanılarak yeniden başlatıldığında (aşağıya bakın) bu yardımcı, yeniden başlatma sırasında sağlanan meta verileri içerir.

Örneğin, bir ödeme uygulaması geliştiriyorsanız belirli bir tutarı aşan bir aktarım yapmadan önce kullanıcıdan onay almak isteyebilirsiniz:

const transferMoney = ai.defineTool({
  name: 'transferMoney',
  description: 'Transfers money between accounts.',
  inputSchema: z.object({
    toAccountId: z.string().describe('the account id of the transfer destination'),
    amount: z.number().describe('the amount in integer cents (100 = $1.00)'),
  }),
  outputSchema: z.object({
    status: z.string().describe('the outcome of the transfer'),
    message: z.string().optional(),
  })
}, async (input, {context, interrupt, resumed})) {
  // if the user rejected the transaction
  if (resumed?.status === "REJECTED") {
    return {status: 'REJECTED', message: 'The user rejected the transaction.'};
  }
  // trigger an interrupt to confirm if amount > $100
  if (resumed?.status !== "APPROVED" && input.amount > 10000) {
    interrupt({
      message: "Please confirm sending an amount > $100.",
    });
  }
  // complete the transaction if not interrupted
  return doTransfer(input);
}

Bu örnekte, ilk çalıştırma sırasında (resumed tanımlanmadığında) araç, tutarın 100 ABD dolarını aşıp aşmadığını kontrol eder ve aşıyorsa bir kesinti tetikler. İkinci çalıştırma sırasında, sağlanan yeni meta verilerde bir durum arar ve onaylanıp onaylanmadığına bağlı olarak aktarımı gerçekleştirir ya da ret yanıtı döndürür.

Kesintiden sonra araçları yeniden başlatma

Kesme araçları şunlar üzerinde tam kontrol sahibi olmanızı sağlar:

  1. İlk araç isteği ne zaman kesinti tetiklemelidir?
  2. Oluşturma döngüsünün ne zaman ve ne zaman devam ettirileceği.
  3. Devam ederken araca hangi ek bilgilerin sağlanacağı.

Önceki bölümde gösterilen örnekte, uygulama, aktarım tutarının doğru olduğundan emin olmak için kullanıcıdan kesintiye uğrayan isteği onaylamasını isteyebilir:

let response = await ai.generate({
  tools: [transferMoney],
  prompt: "Transfer $1000 to account ABC123",
});

while (response.interrupts.length) {
  const confirmations = [];
  // multiple interrupts can be called at once, so we handle them all
  for (const interrupt in response.interrupts) {
    confirmations.push(
      // use the 'restart' method on our tool to provide `resumed` metadata
      transferMoney.restart(
        interrupt,
        // send the tool request input to the user to respond. assume that this
        // returns `{status: "APPROVED"}` or `{status: "REJECTED"}`
        await requestConfirmation(interrupt.toolRequest.input);
      )
    );
  }

  response = await ai.generate({
    tools: [transferMoney],
    messages: response.messages,
    resume: {
      restart: confirmations,
    }
  })
}

// no more interrupts, we can see the final response
console.log(response.text);