Atomic Integrated Analysis with LiteRTDemo

English 中文

Analyze By Demo

This chapter will dissect every real plugin interaction contact point in the LiteRTDemo project through "diagram-text-code" integrated atomic driving.

Topology Step 1

Fig 1: LiteRTDemo Plugin Interaction Topology (Atomic Contact Mapping)

Architecture Step 2

Fig 2: Atomic System Operation Flow (Startup | Usage | Shutdown)

1. Physical Link Initialization

Bootstrapper
Asset Load
Prompting

2. Usage Timing & Sequence

T1
Input Capture→ User presses Enter
T2
Dispatch→ UI triggers component call
T3
Push→ API injects worker thread
T4
Output Stream→ Physical pixel re-injection

3. Physical Shutdown & Recycling

Unbind Delegates
Session Cleanup

Practical Step 3

Developer Integration Guide: Learning from the Demo

This section breaks down all custom code in the Demo project by lifecycle. Rule: All application logic must be present.

Phase 01

Asset Initialization & Physical Loading

Note: You need to learn how to initialize an AI and perform a unique, one-time initialization at the appropriate location in your project.

Build.cs
Provider
Plugin API
Static Module Mount
EnsureModelLoadedAsync
LoadModel(Config)
OnComplete(bSuccess)
1.1 Dependencies | LiteRTDemo.Build.cs
PublicDependencyModuleNames.AddRange(new string[] {
    "Core", "CoreUObject", "Engine", 
    "LiteRTLMUnreal" // Core plugin binary package
});
1.2 Loading Drive | UmgMcpLiteRtLmAiProvider.cpp
void FUmgMcpLiteRtLmAiProvider::EnsureModelLoadedAsync(const FString& AbsPath, TFunction<void(bool)> OnComplete) {
    FLiteRtLmConfig Config = FLiteRtLmUnrealApi::GetAutoConfig();
    Config.ModelPath = AbsPath;
    Config.Backend = TEXT("gpu");

    AsyncTask(ENamedThreads::AnyBackgroundThreadNormalTask, [Config, OnComplete]() {
        bool bSuccess = FLiteRtLmUnrealApi::LoadModel(Config);
        AsyncTask(ENamedThreads::GameThread, [bSuccess, OnComplete]() {
            if (OnComplete) OnComplete(bSuccess);
        });
    });
}
Phase 02

Command Dispatch: Finger to Plugin

Note: You need to learn how to initiate a conversation request to the AI. Specifically, this will require you to update method for async/sync, which is the core input for users.

Widget
Subsystem
Provider
Plugin API
ExecuteSendMessage()
RequestQuestion()
Send(Messages)
SendChatRequest(...)
Level 1: UI Capture | UmgMcpActiveMessageSubsystem.cpp
void UUmgMcpActiveMessageSubsystem::ExecuteSendMessage() {
    auto ChatInput = RegisteredChatInput.Pin();
    if (!ChatInput.IsValid()) return;
    FText InputText = ChatInput->GetText();
    if (!InputText.IsEmpty()) {
        RequestQuestion(InputText.ToString());
        ChatInput->ClearText();
    }
}
Level 2: Protocol Wrap | UmgMcpActiveMessageSubsystem.cpp
void UUmgMcpActiveMessageSubsystem::RequestQuestion(const FString& QuestionText) {
    bIsGenerating = true;
    TSharedPtr<FUmgMcpAgent> ActiveAgent = SessionSubsystem->GetMainAgent();
    if (ActiveAgent.IsValid()) {
        UpdateActiveMessageMeta(ActiveAgent->Name, LOCTEXT("Thinking", "Thinking..."), true);
        TSharedPtr<FJsonObject> RequestObj = MakeShared<FJsonObject>();
        RequestObj->SetStringField(TEXT("role"), TEXT("user"));
        RequestObj->SetStringField(TEXT("content"), QuestionText);
        ActiveAgent->Answer(RequestObj);
    }
}
Level 3: API Injection | FUmgMcpLiteRtLmAiProvider.cpp
void FUmgMcpLiteRtLmAiProvider::Send(const TArray<FUmgMcpChatMessage>& Messages, ...) {
    FLiteRtLmUnrealApi::SendChatRequest(
        AgentPtr, Messages, ToolsJson, OnChunk, OnDone, Params
    );
}
Phase 03

Streaming Feedback: Chunk to Pixel

Note: You need to learn how to obtain results from AI and preferably render them in real-time. Here you need to distinguish between two concepts: Streaming Output and Answer Completion. Streaming output is incremental output for enhancing experience; Answer Completion is the final stock output for implementing business logic.

Plugin
Provider
Subsystem
Widget
Streaming Loop (Multiple Tokens)
OnChunk(FString)
AppendActiveMessageText
AppendToTextOutputBlock
OnDone(Result)
Level 1: Thread Bridge | UmgMcpLiteRtLmAiProvider.cpp
FLiteRtLmChunkCallback OnChunk = [this](const FString& Chunk) {
    AsyncTask(ENamedThreads::GameThread, [this, Chunk]() {
        ActiveSubsystem->AppendActiveMessageText(Chunk); 
    });
};
Level 2: Slot Dispatch | UmgMcpActiveMessageSubsystem.cpp
void UUmgMcpActiveMessageSubsystem::AppendActiveMessageText(const FString& PartialText) {
    if (ActiveMessageWidget.IsValid()) {
        ActiveMessageWidget->AppendToCurrentTextOutputBlock(PartialText);
        if (RegisteredHub.IsValid()) RegisteredHub.Pin()->RefreshVisibility();
    }
}
Level 3: Pixel Refresh | SUmgMcpAgentResponseGroup.cpp
void SUmgMcpAgentResponseGroup::AppendToCurrentTextOutputBlock(const FString& Text) {
    CurrentFullText += Text;
    InternalTextWidget->SetText(FText::FromString(CurrentFullText));
}
Phase 04

Resource Release

Widget
Provider
Plugin API
RemoveAll(this)
UnloadModel()
4.1 VRAM Cleanup | UmgMcpLiteRtLmAiProvider.cpp
void FUmgMcpLiteRtLmAiProvider::UnloadModel() {
    FLiteRtLmUnrealApi::UnloadModel();
}
4.2 Delegate Safety | WinyunqDialogueWidget.cpp
void UWinyunqDialogueWidget::SetTargetNPC(ULiteRtLmComponent* InNPC) {
    if (CurrentNPC) CurrentNPC->OnTextChunkReceived.RemoveAll(this);
}