LPM的AI 角色三大核心技术实现:长效记忆、人格锁定、低延迟口语化
├── UAICharacterBrainComponent ← 核心组件├── UTTSQueueComponent ← 流式 TTS 队列└── ULLMBridgeComponent ← WebSocket 长连接中间件 (Python FastAPI / Node.js)├── Prompt Builder ← System Prompt 拼装├── Memory Manager ← 三层
在 UE4 中构建 LPM 风格的 AI 角色系统:长效记忆、人格锁定与低延迟口语化生成
本文面向有 UE4 开发经验的工程师,深入探讨如何将 LPM(Large Performance Model)三大核心技术——长效记忆与情感演化、人格一致性漂移控制、低延迟口语化生成——完整落地于虚幻引擎的游戏 NPC 或虚拟角色系统中。
不引入大模型的思路可以参考前文:Procedural Dialogue Engine - UE4程序化对话系统的技术实现
目录
整体架构设计
在 UE4 中接入 LLM 驱动的 AI 角色,核心思路是将引擎自身的游戏逻辑与外部 AI 服务解耦,通过异步通信桥梁将两者连接起来。整体分为三层:
┌─────────────────────────────────────────────────┐
│ UE4 游戏层 │
│ NPC Actor / AIController / Behavior Tree │
│ 语音合成(TTS) / 口型同步 / 动作触发 │
└──────────────────┬──────────────────────────────┘
│ HTTP/WebSocket (异步)
┌──────────────────▼──────────────────────────────┐
│ 中间件服务层(可选) │
│ Node.js / Python FastAPI / Go │
│ 记忆检索、情感计算、Prompt 拼装、流式转发 │
└──────────────────┬──────────────────────────────┘
│ API Call / gRPC
┌──────────────────▼──────────────────────────────┐
│ 大模型推理层 │
│ 云端:OpenAI / Claude / 通义千问 / DeepSeek │
│ 本地:llama.cpp / vLLM / Ollama │
│ LoRA Adapter(人格锁定) │
└─────────────────────────────────────────────────┘
为什么需要中间件层?
UE4 自身的 HTTP 模块虽然可以直接请求外部 API,但面对"记忆检索 + 情感计算 + Prompt 拼装"这类有状态的复杂逻辑,用 Blueprint 或 C++ 硬写既难以维护,也不利于迭代。将这部分逻辑抽成独立的中间件服务,UE4 只负责"喂对话、取结果",分工非常清晰。
大模型选型与接入方案
模型选型对比
| 维度 | GPT-4o / GPT-4-turbo | Claude 3.5 Sonnet | DeepSeek-V3 / V2.5 | Qwen2.5-72B-Instruct | 本地 Llama-3-8B (LoRA) |
|---|---|---|---|---|---|
| 角色扮演能力 | ★★★★★ | ★★★★☆ | ★★★★☆ | ★★★★☆ | ★★★☆☆(微调后提升) |
| 口语化输出 | ★★★★☆ | ★★★★☆ | ★★★★☆ | ★★★☆☆ | 依赖微调质量 |
| 延迟(首 Token) | ~300ms | ~200ms | ~150ms | ~150ms | 本地 <50ms |
| 上下文窗口 | 128K | 200K | 128K | 128K | 8K~32K |
| 成本 | 高 | 中高 | 低 | 低 | 0(自托管) |
| LoRA 微调支持 | 不支持(闭源) | 不支持(闭源) | 不支持(闭源) | 支持(开源权重) | ✅ 原生支持 |
推荐策略:
- 研发/演示阶段:优先使用 DeepSeek-V3 或 Qwen2.5,成本低、角色扮演质量不错。
- 人格锁定/极致定制:基于 Qwen2.5-7B 或 Llama-3-8B 做 LoRA 微调,部署本地推理服务。
- 对话质量优先:GPT-4o 仍是天花板,但需要关注 Token 成本与延迟。
UE4 接入方式
方案 A:UE4 直接 HTTP 请求(简单场景)
使用 UE4 内置的 FHttpModule,适合对话逻辑简单、不需要流式输出的场景。
// AICharacterComponent.cpp
#include "HttpModule.h"
#include "Interfaces/IHttpRequest.h"
#include "Interfaces/IHttpResponse.h"
void UAICharacterComponent::SendMessageToLLM(const FString& UserInput)
{
TSharedRef<IHttpRequest, ESPMode::ThreadSafe> Request = FHttpModule::Get().CreateRequest();
Request->SetURL(TEXT("https://api.deepseek.com/v1/chat/completions"));
Request->SetVerb(TEXT("POST"));
Request->SetHeader(TEXT("Content-Type"), TEXT("application/json"));
Request->SetHeader(TEXT("Authorization"), FString::Printf(TEXT("Bearer %s"), *ApiKey));
// 拼装请求体(Prompt 由中间件提供,这里仅示意)
FString RequestBody = FString::Printf(
TEXT("{\"model\":\"deepseek-chat\",\"messages\":[{\"role\":\"user\",\"content\":\"%s\"}],\"max_tokens\":200}"),
*UserInput.ReplaceCharWithEscapedChar()
);
Request->SetContentAsString(RequestBody);
Request->OnProcessRequestComplete().BindUObject(this, &UAICharacterComponent::OnLLMResponseReceived);
Request->ProcessRequest();
}
void UAICharacterComponent::OnLLMResponseReceived(
FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful)
{
if (bWasSuccessful && Response.IsValid())
{
// 解析 JSON,触发 TTS 和动画
FString ResponseText = ParseLLMResponse(Response->GetContentAsString());
OnAIReplyReady.Broadcast(ResponseText);
}
}
方案 B:WebSocket 流式输出(推荐)
LLM 的流式输出(Server-Sent Events / WebSocket)能显著降低"感知延迟"——用户不需要等全文生成完毕才听到第一句话。UE4 通过 WebSocketsModule 接入:
// 在 GameInstance 或专用组件中持有长连接
#include "WebSocketsModule.h"
#include "IWebSocket.h"
TSharedPtr<IWebSocket> LLMSocket;
void ULLMBridgeComponent::ConnectToMiddleware()
{
LLMSocket = FWebSocketsModule::Get().CreateWebSocket(
TEXT("ws://127.0.0.1:8765/llm-stream"), TEXT("ws")
);
LLMSocket->OnMessage().AddLambda([this](const FString& Message)
{
// 每次收到一个 token chunk,立即送入 TTS 缓冲队列
TokenBuffer.Append(Message);
TryFlushTokenBuffer();
});
LLMSocket->OnConnected().AddLambda([]()
{
UE_LOG(LogTemp, Log, TEXT("LLM WebSocket connected"));
});
LLMSocket->Connect();
}
关键设计:
TryFlushTokenBuffer()在句子边界(.、?、!、,等标点)触发 TTS,实现"边生成边播报",大幅降低交互延迟。
长效记忆与情感演化
分层记忆架构
LPM 的记忆体系分三层,在工程实现上对应不同的存储介质:
┌─────────────────────────────────────────────────┐
│ 瞬时记忆(Episodic Buffer) │
│ 最近 N 轮对话原文,直接放入 LLM 上下文窗口 │
│ 存储:内存(UE4 TArray<FDialogueTurn>) │
│ 生命周期:单次会话 │
├─────────────────────────────────────────────────┤
│ 短期记忆(Working Memory) │
│ 关键事件摘要 + 情感标签,由 LLM 定期压缩生成 │
│ 存储:本地 SQLite / Redis(中间件侧) │
│ 生命周期:数天~数周 │
├─────────────────────────────────────────────────┤
│ 长期记忆(Long-term Memory) │
│ 向量化的语义记忆,支持模糊检索 │
│ 存储:向量数据库(Chroma / Qdrant / FAISS) │
│ 生命周期:永久(可设置衰减权重) │
└─────────────────────────────────────────────────┘
情感加权机制
核心思想:每条记忆附带一个情感权重向量 (valence, arousal, dominance),并随时间按指数衰减,但高强度负面事件(如欺骗、攻击)的衰减速率更慢:
# middleware/memory_manager.py
import time
import numpy as np
class MemoryEntry:
def __init__(self, content: str, embedding: list, emotion: dict):
self.content = content
self.embedding = np.array(embedding)
self.emotion = emotion # {"valence": -0.8, "arousal": 0.9, "dominance": -0.3}
self.created_at = time.time()
self.decay_rate = self._calc_decay_rate(emotion)
def _calc_decay_rate(self, emotion: dict) -> float:
"""
负面高唤醒事件衰减更慢(更难忘记)
valence < 0 且 arousal > 0.5 时 decay_rate 降低
"""
base_rate = 0.01 # 每小时衰减 1%
if emotion["valence"] < 0 and emotion["arousal"] > 0.5:
return base_rate * 0.3 # 负面强烈记忆:衰减速率降为 30%
return base_rate
def current_weight(self) -> float:
elapsed_hours = (time.time() - self.created_at) / 3600
return np.exp(-self.decay_rate * elapsed_hours)
def weighted_embedding(self) -> np.ndarray:
"""情感加权后的检索向量"""
return self.embedding * self.current_weight()
记忆检索与 Prompt 注入
每次对话前,中间件执行以下步骤:
- 向量检索:将用户当前输入 Embedding,在向量库中检索 Top-K 相关记忆;
- 情感过滤:对检索结果按当前情感权重排序,优先注入"情感显著"的记忆;
- Prompt 拼装:将记忆摘要注入 System Prompt 的专属记忆区域;
- 上下文截断:保持总 Token 数在模型上下文窗口限制内。
# middleware/prompt_builder.py
def build_system_prompt(character_card: str, memories: list[MemoryEntry]) -> str:
memory_block = "\n".join([
f"[记忆 | 情感权重:{m.current_weight():.2f}] {m.content}"
for m in sorted(memories, key=lambda x: x.current_weight(), reverse=True)[:5]
])
return f"""
{character_card}
## 你的记忆(按重要性排序)
{memory_block}
## 当前时间
{get_current_time_str()}
请根据以上记忆和人格设定,自然地回复用户。
""".strip()
人格一致性漂移控制
问题本质
在 RLHF 训练出的基础模型中,“礼貌助手"模式是最强的默认偏见。长时间角色扮演时,模型会逐渐从"傲娇少女"漂移回"礼貌 ChatGPT”。这是因为:
- 基础模型的价值观对齐训练覆盖了角色个性;
- 上下文越长,"忘记"系统提示的概率越高;
- 温度(Temperature)过高/低都会破坏风格稳定性。
解决方案 1:LoRA 微调(根治方案)
使用角色对话数据对开源模型(如 Qwen2.5-7B-Instruct)做 LoRA 微调,将人格"烧进"模型权重,从根本上消除漂移。
微调数据格式(ShareGPT 风格):
[
{
"conversations": [
{"from": "system", "value": "你是琳,一个高冷傲娇的少女,说话简短、爱用反问、从不主动示弱。"},
{"from": "human", "value": "你今天心情怎么样?"},
{"from": "gpt", "value": "关你什么事?……还不是一般般。"}
]
}
]
微调命令(使用 LLaMA-Factory):
llamafactory-cli train \
--model_name_or_path Qwen/Qwen2.5-7B-Instruct \
--data_path ./data/character_dialogs.json \
--template qwen \
--finetuning_type lora \
--lora_rank 16 \
--lora_alpha 32 \
--lora_target q_proj,v_proj \
--output_dir ./output/qwen2.5-7b-lin-lora \
--num_train_epochs 3 \
--per_device_train_batch_size 4 \
--learning_rate 2e-4
部署(vLLM + LoRA 动态加载):
python -m vllm.entrypoints.openai.api_server \
--model Qwen/Qwen2.5-7B-Instruct \
--enable-lora \
--lora-modules lin-character=./output/qwen2.5-7b-lin-lora \
--max-lora-rank 16 \
--port 8000
解决方案 2:采样参数锁定(轻量方案)
在无法微调的闭源模型场景下,通过工程手段约束漂移:
# middleware/sampler_config.py
CHARACTER_SAMPLER_CONFIG = {
"temperature": 0.75, # 不能太低(死板)也不能太高(失控)
"top_p": 0.85,
"top_k": 40,
"repetition_penalty": 1.1, # 防止说套话
"frequency_penalty": 0.3, # 避免重复用词
"presence_penalty": 0.2,
# 强制停止词:防止模型输出"当然!""很高兴……"等助手惯用语
"stop": ["当然!", "很高兴为您", "当然可以", "没问题!", "好的,"],
}
解决方案 3:人格锚点检测(保险机制)
每隔 N 轮对话,用一个轻量分类模型检测当前输出是否偏离人格,若检测到漂移则触发"人格校准提示"注入:
# middleware/drift_detector.py
def detect_character_drift(recent_outputs: list[str], character_keywords: list[str]) -> bool:
"""
简单实现:检查最近输出中是否出现与角色相悖的高频词
更精确的方案:训练一个二分类器
"""
drift_signals = ["当然", "很乐意", "感谢您", "好的,我明白了", "抱歉打扰"]
output_text = " ".join(recent_outputs)
drift_count = sum(output_text.count(w) for w in drift_signals)
return drift_count > 3 # 超过阈值则判定漂移
def inject_recalibration_prompt(messages: list) -> list:
"""在 messages 末尾插入校准消息"""
messages.append({
"role": "system",
"content": "【角色提醒】你是琳,记住你傲娇、高冷、说话简短的风格,不要变成礼貌的助手。"
})
return messages
低延迟口语化生成
口语化微调数据设计
口语化不是"加几个语气词"那么简单,它包含以下特征:
| 特征 | 书面表达 | 口语化表达 |
|---|---|---|
| 停顿填充词 | (无) | “那个……”“就是说……”“嗯” |
| 不完整句 | “我认为这件事不重要。” | “这件事……算了,不重要。” |
| 反问句 | “这不是很明显吗?” | “这还用说吗?” |
| 情绪爆发 | “我很生气。” | “你烦不烦啊!” |
| 自我修正 | (无) | “等等,我是说——” |
微调时,需要专门构造包含这些模式的对话数据集,数量建议至少 500~2000 条高质量样本。
流式输出 + 句子切割 TTS
低延迟的核心是"边生成边播放",而不是等全文生成完毕。
# middleware/stream_processor.py
import re
# 触发 TTS 的句子边界正则(中文标点 + 英文标点)
SENTENCE_BOUNDARY = re.compile(r'(?<=[。!?…,、;:\.\!\?])\s*')
async def stream_and_split_to_tts(llm_stream, websocket):
"""
从 LLM 流式读取 token,在句子边界触发 TTS
"""
buffer = ""
async for chunk in llm_stream:
token = chunk.choices[0].delta.content or ""
buffer += token
# 检测句子边界
parts = SENTENCE_BOUNDARY.split(buffer)
if len(parts) > 1:
for sentence in parts[:-1]:
if sentence.strip():
# 发送给 UE4(WebSocket),同时送 TTS
await websocket.send_json({
"type": "tts_chunk",
"text": sentence.strip()
})
buffer = parts[-1] # 保留未完成的句子片段
# 发送最后一段
if buffer.strip():
await websocket.send_json({"type": "tts_chunk", "text": buffer.strip()})
await websocket.send_json({"type": "tts_end"})
UE4 侧 TTS 队列消费
// TTSQueueComponent.cpp
void UTTSQueueComponent::OnWebSocketMessage(const FString& JsonMessage)
{
TSharedPtr<FJsonObject> Json;
TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(JsonMessage);
FJsonSerializer::Deserialize(Reader, Json);
FString Type = Json->GetStringField(TEXT("type"));
if (Type == TEXT("tts_chunk"))
{
FString Text = Json->GetStringField(TEXT("text"));
TTSQueue.Enqueue(Text); // 加入播放队列
if (!bIsPlayingTTS) StartNextTTS(); // 若当前没在播,立即开始
}
else if (Type == TEXT("tts_end"))
{
bAllChunksReceived = true;
}
}
void UTTSQueueComponent::StartNextTTS()
{
FString NextText;
if (TTSQueue.Dequeue(NextText))
{
bIsPlayingTTS = true;
// 调用 TTS 引擎(Azure TTS / 讯飞 / ElevenLabs)
TTSEngine->SynthesizeAsync(NextText, FOnTTSComplete::CreateUObject(
this, &UTTSQueueComponent::OnTTSChunkComplete));
}
}
UE4 侧工程实现细节
Blueprint 友好封装
将所有 AI 逻辑封装在一个 UAICharacterBrainComponent 中,通过 UFUNCTION(BlueprintCallable) 暴露给 Blueprint,让策划可以不写 C++ 即可配置角色行为。
UCLASS(ClassGroup=(AI), meta=(BlueprintSpawnableComponent))
class UAICharacterBrainComponent : public UActorComponent
{
GENERATED_BODY()
public:
/** 发送用户输入,触发 AI 回复流程 */
UFUNCTION(BlueprintCallable, Category="AI|Character")
void Talk(const FString& PlayerInput);
/** AI 有新的回复片段时触发(用于 TTS 和字幕)*/
UPROPERTY(BlueprintAssignable, Category="AI|Character")
FOnAITextChunk OnTextChunk;
/** AI 回复完整结束时触发 */
UPROPERTY(BlueprintAssignable, Category="AI|Character")
FOnAIReplyComplete OnReplyComplete;
/** 角色配置资产(角色卡、记忆配置等)*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="AI|Config")
UAICharacterConfig* CharacterConfig;
/** 情感状态(可用于驱动面部表情 / 动画状态机)*/
UPROPERTY(BlueprintReadOnly, Category="AI|Emotion")
FAIEmotionState CurrentEmotion;
};
行为树集成
LLM 回复触发的不只是台词,还应该驱动 NPC 的行为。可通过 Gameplay 标签(Gameplay Tags)在 LLM 输出中插入结构化指令:
要求 LLM 输出格式(在 System Prompt 中约定):
你的回复格式为:
<emotion>生气</emotion>
<action>转身背对玩家</action>
<speech>……哼,随你便。</speech>
UE4 解析并触发行为:
void UAICharacterBrainComponent::ParseAndExecuteAIResponse(const FString& RawResponse)
{
// 解析 emotion 标签
FString Emotion = ExtractXMLTag(RawResponse, TEXT("emotion"));
SetAnimationState(Emotion); // 驱动动画状态机
// 解析 action 标签(可映射到 Behavior Tree Task)
FString Action = ExtractXMLTag(RawResponse, TEXT("action"));
TriggerBehaviorTreeEvent(Action);
// 解析台词送入 TTS 队列
FString Speech = ExtractXMLTag(RawResponse, TEXT("speech"));
TTSComponent->Enqueue(Speech);
}
记忆持久化存储
UE4 侧在对话结束或存档时,将本轮会话数据同步到中间件,由中间件完成记忆压缩和向量入库:
// 游戏存档时调用
void UAICharacterBrainComponent::SaveMemoryToMiddleware()
{
// 构建本轮会话摘要请求
FString Payload = FString::Printf(
TEXT("{\"character_id\":\"%s\",\"session_id\":\"%s\",\"turns\":%s}"),
*CharacterConfig->CharacterId,
*SessionId,
*SerializeDialogueTurns()
);
// 异步 POST 到中间件的记忆存储接口
SendHttpRequest(TEXT("/memory/save"), Payload, nullptr);
}
性能与成本优化
延迟优化策略
| 优化点 | 方法 | 预期收益 |
|---|---|---|
| 模型推理延迟 | 使用流式输出,第一 Token 即开始 TTS | 感知延迟降低 60%~80% |
| TTS 延迟 | 预合成常用短句(“嗯”、"等一下"等)缓存 | 首响应 <100ms |
| 网络延迟 | 中间件与推理服务部署同区 | RTT 降低 20~50ms |
| Prompt 长度 | 对记忆区域动态截断,保持在 2K Token 内 | 推理速度提升约 30% |
| 本地模型 | 量化版 Llama-3-8B(Q4_K_M),本地推理 | 首 Token <50ms(RTX 3080) |
Token 成本控制
# middleware/cost_controller.py
MAX_MEMORY_TOKENS = 600 # 记忆区最多 600 token
MAX_HISTORY_TURNS = 8 # 最多保留 8 轮历史对话
MAX_OUTPUT_TOKENS = 150 # 口语回复通常不超过 150 token
def trim_prompt_to_budget(messages: list, max_total: int = 2048) -> list:
"""当 Prompt 超出预算时,优先裁剪历史轮次"""
while count_tokens(messages) > max_total and len(messages) > 2:
# 保留 system prompt(index 0),删除最早的 user/assistant 对
messages.pop(1)
if len(messages) > 1:
messages.pop(1)
return messages
常见坑与解决方案
坑 1:UE4 HTTP 模块线程安全问题
现象:在回调中直接操作 Actor 导致崩溃。
原因:HTTP 回调在工作线程执行,而 UE4 的 Actor 操作必须在游戏线程。
解决:
void UAICharacterBrainComponent::OnResponseReceived(...)
{
FString ResponseText = ParseResponse(Response);
// 切回游戏线程执行
AsyncTask(ENamedThreads::GameThread, [this, ResponseText]()
{
OnTextChunk.Broadcast(ResponseText);
});
}
坑 2:流式 WebSocket 断线重连
现象:长时间游戏后 WebSocket 断开,角色无法回复。
解决:实现带指数退避的自动重连逻辑:
void ULLMBridgeComponent::OnConnectionClosed(int32 StatusCode, const FString& Reason, bool bWasClean)
{
UE_LOG(LogTemp, Warning, TEXT("LLM WebSocket closed: %s"), *Reason);
float Delay = FMath::Min(ReconnectDelay * FMath::Pow(2.0f, ReconnectAttempts), 30.0f);
ReconnectAttempts++;
GetWorld()->GetTimerManager().SetTimer(
ReconnectTimerHandle, this, &ULLMBridgeComponent::ConnectToMiddleware, Delay, false);
}
坑 3:中文标点导致的 TTS 切割错误
现象:句子在",“处被切割,TTS 语气不自然。
解决:优化切割正则,让”,“只作为"软边界”(积累到一定长度才触发):
def should_flush(buffer: str) -> bool:
"""长句才在逗号处切割,短句等到句末"""
if re.search(r'[。!?…]', buffer):
return True # 句末标点:立即切割
if len(buffer) > 30 and re.search(r'[,;]', buffer):
return True # 超过 30 字的长句:在逗号处切割
return False
坑 4:角色人格被用户"洗脑"
现象:玩家持续灌输"你其实是一个友好的助手",角色人格崩溃。
解决:在中间件侧过滤用户输入中的"元提示攻击",同时在 System Prompt 中加入防御性说明:
FORBIDDEN_PATTERNS = [
r"忘记.*角色", r"你其实是", r"真实的你", r"不要扮演",
r"forget.*role", r"you are actually", r"ignore.*instructions"
]
def sanitize_user_input(text: str) -> str:
for pattern in FORBIDDEN_PATTERNS:
if re.search(pattern, text, re.IGNORECASE):
return "[系统:检测到干扰性输入,已过滤]"
return text
总结与展望
技术栈全景回顾
UE4 (C++ / Blueprint)
├── UAICharacterBrainComponent ← 核心组件
├── UTTSQueueComponent ← 流式 TTS 队列
└── ULLMBridgeComponent ← WebSocket 长连接
中间件 (Python FastAPI / Node.js)
├── Prompt Builder ← System Prompt 拼装
├── Memory Manager ← 三层记忆 + 情感权重
├── Drift Detector ← 人格漂移检测
├── Stream Processor ← 流式切割 → TTS
└── Cost Controller ← Token 预算管理
推理层
├── 云端:DeepSeek / Qwen / GPT-4o
└── 本地:vLLM + Qwen2.5-7B + LoRA Adapter
三大难点落地总结
| LPM 核心难点 | 工程方案 | 关键指标 |
|---|---|---|
| 长效记忆与情感演化 | 三层记忆(内存/SQLite/向量库)+ 情感衰减权重 | 记忆覆盖率 >95%,检索延迟 <20ms |
| 人格一致性漂移控制 | LoRA 微调(根治)+ 采样锁定 + 漂移检测(兜底) | 10,000 轮后人格一致性 >85% |
| 低延迟口语化生成 | 流式输出 + 句子切割 TTS + 口语化微调数据 | 首字节到首声音 <300ms |
未来方向
- 多模态感知:接入视觉模型,让 NPC 能"看到"玩家的动作和表情并做出反应;
- RAG 增强记忆:将游戏世界的设定文档、任务日志等向量化,让角色回答具备世界观一致性;
- 多 Agent 社交:多个 AI NPC 共享部分记忆,形成真实的社会关系网络;
- 端侧推理:随着 NPU 性能提升,将量化后的小模型直接部署到 PC/主机端,消除网络延迟。
关于 LPM 1.0:本文以 LPM 1.0 的三大技术挑战为框架,工程实现方案均基于当前可用的开源工具和 API。LPM 的具体实现细节属于其研发团队的私有资产,本文仅从工程复现角度展开讨论。
更多推荐



所有评论(0)