경고
의미 체계 커널 프로세스 프레임워크 아직 개발 중이며 변경될 수 있습니다.
개요
이전 섹션에서는 새 제품에 대한 설명서 생성을 자동화하는 데 도움이 되는 프로세스를 빌드했습니다. 이제 프로세스에서 제품과 관련된 설명서를 생성할 수 있으며, 교정 및 편집 주기를 통해 실행하여 품질 표시줄을 충족할 수 있습니다. 이 섹션에서는 문서를 게시하기 전에 사용자가 승인하거나 거부하도록 요구하여 해당 프로세스를 다시 개선할 것입니다. 프로세스 프레임워크의 유연성은 여러 가지 방법으로 이 작업을 수행할 수 있다는 것을 의미하지만, 이 예제에서는 승인을 요청하기 위해 외부 pubsub 시스템과의 통합을 보여 줍니다.
게시가 승인을 기다리도록 설정
프로세스에 대한 첫 번째 변경 내용은 게시 단계가 문서를 게시하기 전에 승인을 기다리도록 하는 것입니다. 한 가지 옵션은 PublishDocumentation
PublishDocumentationStep
함수에 승인을 위한 두 번째 매개 변수를 추가하는 것입니다. 이는 모든 필수 매개 변수가 제공된 경우에만 단계의 KernelFunction이 호출되기 때문에 작동합니다.
// 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;
}
}
Python 휴먼 인 더 루프 프로세스 동작에 대한 지원은 곧 제공될 예정입니다.
위의 코드를 사용하면 생성된 설명서가 PublishDocumentation
매개 변수로 전송되고 승인 결과가 PublishDocumentationStep
매개 변수로 전송된 경우에만 document
userApproval
함수가 호출됩니다.
이제 기존 단계 논리 ProofreadStep
를 다시 사용하여 외부 pubsub 시스템에 이벤트를 추가로 내보낼 수 있습니다. 그러면 사용자 승인자에게 새 요청이 있음을 알릴 수 있습니다.
// 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);
}
...
}
새로 생성된 설명서는 교정 에이전트의 승인을 받을 때 게시하려고 하므로 승인된 문서는 게시 단계에서 큐에 대기됩니다. 또한 최신 문서에 대한 업데이트가 포함된 외부 pubsub 시스템을 통해 사람이 알림을 받게 됩니다. 이 새로운 디자인과 일치하도록 프로세스 흐름을 업데이트해 보겠습니다.
Python 휴먼 인 더 루프 프로세스 동작에 대한 지원은 곧 제공될 예정입니다.
// 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;
마지막으로, 인터페이스 IExternalKernelProcessMessageChannel
의 구현을 제공해야 합니다. 이는 새 ProxyStep
이 내부적으로 사용하기 때문입니다. 이 인터페이스는 외부에서 메시지를 내보내는 데 사용됩니다. 이 인터페이스의 구현은 사용 중인 외부 시스템에 따라 달라집니다. 이 예제에서는 만든 사용자 지정 클라이언트를 사용하여 외부 pubsub 시스템에 메시지를 보냅니다.
// 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();
}
}
}
마지막으로 프로세스 ProxyStep
가 IExternalKernelProcessMessageChannel
구현을 이 경우 MyCloudEventClient
사용할 수 있도록 하려면, 제대로 파이프해야 합니다.
로컬 런타임을 사용하는 경우 StartAsync
을(를) 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)
Dapr 런타임을 사용하는 경우 프로젝트의 프로그램 설정에서 종속성 주입을 통해 배관을 수행해야 합니다.
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>();
Python 휴먼 인 더 루프 프로세스 동작에 대한 지원은 곧 제공될 예정입니다.
프로세스 흐름에 두 가지 변경 내용이 적용되었습니다.
-
HumanApprovalResponse
단계의userApproval
매개 변수로 라우팅될docsPublishStep
입력 이벤트가 추가되었습니다. -
docsPublishStep
KernelFunction에는 이제 두 개의 매개 변수가 있으므로 기존 경로를 업데이트하여document
매개 변수 이름을 지정해야 합니다.
이전과 마찬가지로 프로세스를 실행하고, 이번에는 proofreader가 생성된 설명서를 승인하고 document
단계의 docPublishStep
매개 변수로 보낼 때 userApproval
매개 변수를 기다리고 있으므로 단계가 더 이상 호출되지 않습니다. 이 시점에서 호출할 준비가 된 단계가 없고 프로세스를 시작하기 위해 수행한 호출이 반환되므로 프로세스가 유휴 상태가 됩니다. 이 프로세스는 "휴먼 인더 루프"가 게시 요청을 승인하거나 거부하는 작업을 수행할 때까지 이 유휴 상태로 유지됩니다. 이 문제가 발생하고 결과가 프로그램에 다시 전달되면 결과를 사용하여 프로세스를 다시 시작할 수 있습니다.
// Restart the process with approval for publishing the documentation.
await process.StartAsync(kernel, new KernelProcessEvent { Id = "UserApprovedDocument", Data = true });
Python 휴먼 인 더 루프 프로세스 동작에 대한 지원은 곧 제공될 예정입니다.
프로세스가 UserApprovedDocument
에 의해 다시 시작되면, 중단된 지점에서 이어서 진행하고, docsPublishStep
로 설정된 userApproval
값을 사용하여 true
을 호출하며, 문서가 게시됩니다. 이벤트 UserRejectedDocument
로 다시 시작되면 프로세스는 ApplySuggestions
단계에서 docsGenerationStep
함수를 시작하고, 프로세스는 이전과 같이 계속됩니다.
이제 프로세스가 완료되었으며 프로세스에 휴먼 인 더 루프 단계를 성공적으로 추가했습니다. 이제 이 프로세스를 사용하여 제품에 대한 설명서를 생성하고, 교정하고, 사람이 승인한 후에 게시할 수 있습니다.