Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Peringatan
Kerangka Kerja Proses Kernel Semantik bersifat eksperimental, masih dalam pengembangan dan dapat berubah.
Ikhtisar
Di bagian sebelumnya, kami membangun Proses untuk membantu kami mengotomatiskan pembuatan dokumentasi untuk produk baru kami. Proses kami sekarang dapat menghasilkan dokumentasi yang khusus untuk produk kami, dan dapat memastikannya memenuhi bilah kualitas kami dengan menjalankannya melalui siklus proofread dan edit. Di bagian ini kami akan meningkatkan proses itu lagi dengan mengharuskan manusia menyetujui atau menolak dokumentasi sebelum diterbitkan. Fleksibilitas kerangka kerja proses berarti bahwa ada beberapa cara untuk melakukan ini tetapi dalam contoh ini kami akan menunjukkan integrasi dengan sistem pubsub eksternal untuk meminta persetujuan.
Mengatur penerbitan untuk menunggu persetujuan
Perubahan pertama yang perlu kita lakukan pada prosesnya adalah membuat langkah penerbitan menunggu persetujuan sebelum menerbitkan dokumentasi. Salah satu opsinya adalah dengan hanya menambahkan parameter kedua untuk persetujuan ke fungsi PublishDocumentation di PublishDocumentationStep. Ini berfungsi karena KernelFunction dalam langkah hanya akan dipanggil ketika semua parameter yang diperlukan telah disediakan.
// A process step to publish documentation
public class PublishDocumentationStep : KernelProcessStep
{
[KernelFunction]
public DocumentInfo PublishDocumentation(DocumentInfo document, bool userApproval) // added the userApproval parameter
{
// Only publish the documentation if it has been approved
if (userApproval)
{
// For example purposes we just write the generated docs to the console
Console.WriteLine($"[{nameof(PublishDocumentationStep)}]:\tPublishing product documentation approved by user: \n{document.Title}\n{document.Content}");
}
return document;
}
}
Dukungan untuk perilaku Proses Python Human-in-the-loop akan segera hadir.
Dengan kode di atas, fungsi PublishDocumentation dalam PublishDocumentationStep hanya akan dipanggil ketika dokumentasi yang dihasilkan telah dikirim ke parameter document dan hasil persetujuan telah dikirim ke parameter userApproval.
Kita sekarang dapat menggunakan kembali logika langkah ProofreadStep yang ada untuk mengirimkan peristiwa tambahan ke sistem pubsub eksternal kita yang akan memperingatkan pihak yang memberi persetujuan bahwa ada permintaan baru.
// A process step to publish documentation
public class ProofReadDocumentationStep : KernelProcessStep
{
...
if (formattedResponse.MeetsExpectations)
{
// Events that are getting piped to steps that will be resumed, like PublishDocumentationStep.OnPublishDocumentation
// require events to be marked as public so they are persisted and restored correctly
await context.EmitEventAsync("DocumentationApproved", data: document, visibility: KernelProcessEventVisibility.Public);
}
...
}
Karena kami ingin menerbitkan dokumentasi yang baru dibuat ketika disetujui oleh agen proofread, dokumen yang disetujui akan diantrekan pada langkah penerbitan. Selain itu, seorang pengguna akan menerima pemberitahuan melalui sistem pubsub eksternal kami yang berisi pembaruan terbaru pada dokumen terkini. Mari kita perbarui alur proses agar sesuai dengan desain baru ini.
Dukungan untuk perilaku Proses Python Human-in-the-loop akan segera hadir.
// Create the process builder
ProcessBuilder processBuilder = new("DocumentationGeneration");
// Add the steps
var infoGatheringStep = processBuilder.AddStepFromType<GatherProductInfoStep>();
var docsGenerationStep = processBuilder.AddStepFromType<GenerateDocumentationStepV2>();
var docsProofreadStep = processBuilder.AddStepFromType<ProofreadStep>();
var docsPublishStep = processBuilder.AddStepFromType<PublishDocumentationStep>();
// internal component that allows emitting SK events externally, a list of topic names
// is needed to link them to existing SK events
var proxyStep = processBuilder.AddProxyStep(["RequestUserReview", "PublishDocumentation"]);
// Orchestrate the events
processBuilder
.OnInputEvent("StartDocumentGeneration")
.SendEventTo(new(infoGatheringStep));
processBuilder
.OnInputEvent("UserRejectedDocument")
.SendEventTo(new(docsGenerationStep, functionName: "ApplySuggestions"));
// When external human approval event comes in, route it to the 'isApproved' parameter of the docsPublishStep
processBuilder
.OnInputEvent("UserApprovedDocument")
.SendEventTo(new(docsPublishStep, parameterName: "userApproval"));
// Hooking up the rest of the process steps
infoGatheringStep
.OnFunctionResult()
.SendEventTo(new(docsGenerationStep, functionName: "GenerateDocumentation"));
docsGenerationStep
.OnEvent("DocumentationGenerated")
.SendEventTo(new(docsProofreadStep));
docsProofreadStep
.OnEvent("DocumentationRejected")
.SendEventTo(new(docsGenerationStep, functionName: "ApplySuggestions"));
// When the proofreader approves the documentation, send it to the 'document' parameter of the docsPublishStep
// Additionally, the generated document is emitted externally for user approval using the pre-configured proxyStep
docsProofreadStep
.OnEvent("DocumentationApproved")
// [NEW] addition to emit messages externally
.EmitExternalEvent(proxyStep, "RequestUserReview") // Hooking up existing "DocumentationApproved" to external topic "RequestUserReview"
.SendEventTo(new(docsPublishStep, parameterName: "document"));
// When event is approved by user, it gets published externally too
docsPublishStep
.OnFunctionResult()
// [NEW] addition to emit messages externally
.EmitExternalEvent(proxyStep, "PublishDocumentation");
var process = processBuilder.Build();
return process;
Akhirnya, implementasi antarmuka IExternalKernelProcessMessageChannel harus disediakan karena digunakan secara internal oleh yang baru ProxyStep. Antarmuka ini digunakan untuk memancarkan pesan secara eksternal. Implementasi antarmuka ini akan bergantung pada sistem eksternal yang Anda gunakan. Dalam contoh ini, kita akan menggunakan klien kustom yang telah kita buat untuk mengirim pesan ke sistem pubsub eksternal.
// Example of potential custom IExternalKernelProcessMessageChannel implementation
public class MyCloudEventClient : IExternalKernelProcessMessageChannel
{
private MyCustomClient? _customClient;
// Example of an implementation for the process
public async Task EmitExternalEventAsync(string externalTopicEvent, KernelProcessProxyMessage message)
{
// logic used for emitting messages externally.
// Since all topics are received here potentially
// some if else/switch logic is needed to map correctly topics with external APIs/endpoints.
if (this._customClient != null)
{
switch (externalTopicEvent)
{
case "RequestUserReview":
var requestDocument = message.EventData.ToObject() as DocumentInfo;
// As an example only invoking a sample of a custom client with a different endpoint/api route
this._customClient.InvokeAsync("REQUEST_USER_REVIEW", requestDocument);
return;
case "PublishDocumentation":
var publishedDocument = message.EventData.ToObject() as DocumentInfo;
// As an example only invoking a sample of a custom client with a different endpoint/api route
this._customClient.InvokeAsync("PUBLISH_DOC_EXTERNALLY", publishedDocument);
return;
}
}
}
public async ValueTask Initialize()
{
// logic needed to initialize proxy step, can be used to initialize custom client
this._customClient = new MyCustomClient("http://localhost:8080");
this._customClient.Initialize();
}
public async ValueTask Uninitialize()
{
// Cleanup to be executed when proxy step is uninitialized
if (this._customClient != null)
{
await this._customClient.ShutdownAsync();
}
}
}
Akhirnya untuk memungkinkan proses ProxyStep memanfaatkan implementasi IExternalKernelProcessMessageChannel, dalam hal MyCloudEventClient ini, kita perlu menyalurkannya dengan tepat.
Saat menggunakan Lingkungan Runtime Lokal, kelas yang diimplementasikan dapat diteruskan saat memanggil StartAsync di kelas KernelProcess.
KernelProcess process;
IExternalKernelProcessMessageChannel myExternalMessageChannel = new MyCloudEventClient();
// Start the process with the external message channel
await process.StartAsync(kernel, new KernelProcessEvent
{
Id = inputEvent,
Data = input,
},
myExternalMessageChannel)
Saat menggunakan Dapr Runtime, pipa harus dilakukan melalui injeksi dependensi pada penyiapan program proyek.
var builder = WebApplication.CreateBuilder(args);
...
// depending on the application a singleton or scoped service can be used
// Injecting SK Process custom client IExternalKernelProcessMessageChannel implementation
builder.Services.AddSingleton<IExternalKernelProcessMessageChannel, MyCloudEventClient>();
Dukungan untuk perilaku Proses Python Human-in-the-loop akan segera hadir.
Dua perubahan telah dilakukan pada alur proses:
- Menambahkan peristiwa input bernama
HumanApprovalResponseyang akan dialihkan ke parameteruserApprovalpada langkahdocsPublishStep. - Karena KernelFunction di
docsPublishStepsekarang memiliki dua parameter, kita perlu memperbarui rute yang ada untuk menentukan nama parameterdocument.
Jalankan proses seperti yang Anda lakukan sebelumnya dan perhatikan bahwa kali ini ketika proofreader menyetujui dokumentasi yang dihasilkan dan mengirimkannya ke parameter document langkah docPublishStep, langkah tersebut tidak lagi dipanggil karena menunggu parameter userApproval. Pada titik ini proses berjalan diam karena tidak ada langkah-langkah yang siap untuk dipanggil dan panggilan yang kami buat untuk memulai proses kembali. Proses akan tetap dalam keadaan diam ini sampai "manusia dalam putaran" kami mengambil tindakan untuk menyetujui atau menolak permintaan penerbitan. Setelah ini terjadi dan hasilnya telah dikomunikasikan kembali ke program kami, kita dapat memulai ulang proses dengan hasilnya.
// Restart the process with approval for publishing the documentation.
await process.StartAsync(kernel, new KernelProcessEvent { Id = "UserApprovedDocument", Data = true });
Dukungan untuk perilaku Proses Python Human-in-the-loop akan segera hadir.
Ketika proses itu dimulai lagi dengan UserApprovedDocument, proses akan dilanjutkan dari tempat terakhir dan kemudian menjalankan docsPublishStep dengan userApproval diatur ke true, dan dokumentasi kami akan diterbitkan. Jika dimulai ulang dengan UserRejectedDocument event, proses akan memulai fungsi ApplySuggestions dalam langkah docsGenerationStep dan proses akan berlanjut seperti sebelumnya.
Prosesnya sekarang selesai dan kami telah berhasil menambahkan langkah human-in-the-loop ke dalam proses kami. Proses ini sekarang dapat digunakan untuk menghasilkan dokumentasi untuk produk kami, memeriksanya, dan menerbitkannya setelah disetujui oleh manusia.