Atomic Integrated Analysis with LiteRTDemo

English 运行解剖

Analyze By Demo

本章将通过“图文码”一体化的原子驱动,拆解 LiteRTDemo 项目中每一个真实的插件交互触点。

Topology Step 1

图 1: LiteRTDemo 插件交互拓扑 (原子触点映射)

Architecture Step 2

图 2: 系统原子运行全流程 (初始化流程 | 使用原子时序 | 物理销毁)

1. 初始化物理链路 (Startup Logic)

Bootstrapper
资产加载
人格注入

2. 使用原子时序 (Usage Timing & Sequence)

T1
意图捕获 (Input)→ 用户按下回车
T2
指令派遣 (Dispatch)→ UI 触发组件调用
T3
指令注入 (Push)→ API 注入后台计算线程
T4
流式渲染 (Output)→ 物理回灌 UMG 像素

3. 物理销毁与回收 (Cleanup)

断开代理
Session 回收

Practical Step 3

开发者集成指南:学习 Demo 中驱动插件的方法

本节将 Demo 项目中所有非插件、非引擎的自定义代码按生命周期拆解。写全准则:除底层 API 外,所有应用层逻辑必须在位。

Phase 01

资产初始化与物理加载

提示:你需要学习如何初始化一个 AI 并且在你的项目合适的地方让其进行一次唯一的初始化。

Build.cs
Provider
Plugin API
静态模块挂载
EnsureModelLoadedAsync
LoadModel(Config)
OnComplete(bSuccess)
1.1 模块依赖 | LiteRTDemo.Build.cs
PublicDependencyModuleNames.AddRange(new string[] {
    "Core", "CoreUObject", "Engine", 
    "LiteRTLMUnreal" // 插件核心二进制包
});
1.2 物理加载驱动 | 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

指令下行:从指尖到插件

提示:你需要学习如何向 AI 发起对话请求,特别的这会要求你接下来需要异步同步的方法更新,这是用户使用的核心输入。

Widget
Subsystem
Provider
Plugin API
ExecuteSendMessage()
RequestQuestion()
Send(Messages)
SendChatRequest(Agent, Msg, Tools...)
一级派遣:UI 意图捕获 | 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();
    }
}
二级派遣:中枢协议封装 | 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);
    }
}
三级派遣:插件 API 注入 | FUmgMcpLiteRtLmAiProvider.cpp
void FUmgMcpLiteRtLmAiProvider::Send(const TArray<FUmgMcpChatMessage>& Messages, ...) {
    FLiteRtLmUnrealApi::SendChatRequest(
        AgentPtr, Messages, ToolsJson, OnChunk, OnDone, Params
    );
}
Phase 03

流式回灌:从碎片到像素

提示:你需要学习如何从 AI 中取得结果并且最好实时渲染。这里你需要区分两个概念:流式输出和回答完成。流式输出是增量输出,用于增强体验;回答完成是存量输出,用于实现业务逻辑。

Plugin
Provider
Subsystem
Widget
Streaming Loop (Multiple Tokens)
OnChunk(FString)
AppendActiveMessageText
AppendToTextOutputBlock
OnDone(Result)
一级回灌:线程切换与中转 | UmgMcpLiteRtLmAiProvider.cpp
FLiteRtLmChunkCallback OnChunk = [this](const FString& Chunk) {
    AsyncTask(ENamedThreads::GameThread, [this, Chunk]() {
        ActiveSubsystem->AppendActiveMessageText(Chunk); 
    });
};
二级回灌:活跃槽位调度 | UmgMcpActiveMessageSubsystem.cpp
void UUmgMcpActiveMessageSubsystem::AppendActiveMessageText(const FString& PartialText) {
    if (ActiveMessageWidget.IsValid()) {
        ActiveMessageWidget->AppendToCurrentTextOutputBlock(PartialText);
        if (RegisteredHub.IsValid()) RegisteredHub.Pin()->RefreshVisibility();
    }
}
三级回灌:像素刷新 | SUmgMcpAgentResponseGroup.cpp
void SUmgMcpAgentResponseGroup::AppendToCurrentTextOutputBlock(const FString& Text) {
    CurrentFullText += Text;
    InternalTextWidget->SetText(FText::FromString(CurrentFullText));
}
Phase 04

资源卸载与物理回收

Widget
Provider
Plugin API
RemoveAll(this)
UnloadModel()
4.1 显存物理释放 | UmgMcpLiteRtLmAiProvider.cpp
void FUmgMcpLiteRtLmAiProvider::UnloadModel() {
    FLiteRtLmUnrealApi::UnloadModel();
}
4.2 代理断路逻辑 | WinyunqDialogueWidget.cpp
void UWinyunqDialogueWidget::SetTargetNPC(ULiteRtLmComponent* InNPC) {
    if (CurrentNPC) CurrentNPC->OnTextChunkReceived.RemoveAll(this);
}