refactor(context): add ResolvedContext as response of ContextWorkspace#resolve, integrated with Message encoding

This commit is contained in:
2026-03-24 11:04:03 +08:00
parent d7179364a1
commit 4494d58ff9
4 changed files with 70 additions and 37 deletions

View File

@@ -24,9 +24,9 @@ class ContextWorkspace {
* 根据传入的 [ContextBlock.VisibleDomain] 列表,获取上下文块
* @param domains 需要获取上下文的域列表,顺序将决定权重优先级,按照列表排序将具备线性权重分层,最终反映到 blockContent 列表的排序上
*/
fun resolve(domains: List<ContextBlock.VisibleDomain>): List<BlockContent> = lock.write {
fun resolve(domains: List<ContextBlock.VisibleDomain>): ResolvedContext = lock.write {
if (domains.isEmpty()) {
return@write emptyList()
return@write ResolvedContext(emptyList())
}
val primaryDomain = domains.first()
@@ -58,7 +58,7 @@ class ContextWorkspace {
)
}
activeBlocks
val blocks = activeBlocks
.sortedWith(
compareBy<ResolvedContextBlock> { it.domainWeight }
.thenBy { it.block.sourceKey.blockName }
@@ -73,6 +73,7 @@ class ContextWorkspace {
resolved.block.render()
}
}
ResolvedContext(blocks)
}

View File

@@ -0,0 +1,61 @@
package work.slhaf.partner.core.cognition
import org.w3c.dom.Document
import work.slhaf.partner.api.chat.pojo.Message
import java.io.StringWriter
import javax.xml.parsers.DocumentBuilderFactory
import javax.xml.transform.OutputKeys
import javax.xml.transform.TransformerFactory
import javax.xml.transform.dom.DOMSource
import javax.xml.transform.stream.StreamResult
data class ResolvedContext(
val blocks: List<BlockContent>
) {
fun encodeToContextMessage(): Message {
val content = if (blocks.isEmpty()) {
"<no_context></no_context>"
} else {
buildContextXml(blocks)
}
return Message(Message.Character.USER, content)
}
private fun buildContextXml(blocks: List<BlockContent>): String {
return try {
val document = newDocument()
val root = document.createElement("context")
document.appendChild(root)
blocks.stream()
.map(BlockContent::encodeToXml)
.forEach { blockElement ->
root.appendChild(document.importNode(blockElement, true))
}
toXmlString(document)
} catch (e: Exception) {
throw IllegalStateException("构建 context 区段失败", e)
}
}
private fun newDocument(): Document {
return DocumentBuilderFactory.newInstance()
.newDocumentBuilder()
.newDocument()
}
private fun toXmlString(document: Document): String {
val transformer = TransformerFactory.newInstance().newTransformer().apply {
setOutputProperty(OutputKeys.INDENT, "yes")
setOutputProperty(OutputKeys.ENCODING, "UTF-8")
setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes")
setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2")
}
return StringWriter().use { writer ->
transformer.transform(DOMSource(document), StreamResult(writer))
writer.toString()
}
}
}

View File

@@ -15,7 +15,6 @@ import work.slhaf.partner.core.action.entity.cache.CacheAdjustData;
import work.slhaf.partner.core.action.entity.cache.CacheAdjustMetaData;
import work.slhaf.partner.core.cognition.CognitionCapability;
import work.slhaf.partner.core.memory.MemoryCapability;
import work.slhaf.partner.core.perceive.PerceiveCapability;
import work.slhaf.partner.module.modules.action.executor.ActionExecutor;
import work.slhaf.partner.module.modules.action.planner.confirmer.ActionConfirmer;
import work.slhaf.partner.module.modules.action.planner.confirmer.entity.ConfirmerInput;
@@ -54,8 +53,6 @@ public class ActionPlanner extends AbstractAgentModule.Running<PartnerRunningFlo
@InjectCapability
private ActionCapability actionCapability;
@InjectCapability
private PerceiveCapability perceiveCapability;
@InjectCapability
private MemoryCapability memoryCapability;
@InjectModule

View File

@@ -11,10 +11,7 @@ import work.slhaf.partner.api.agent.factory.component.abstracts.AbstractAgentMod
import work.slhaf.partner.api.agent.factory.component.abstracts.ActivateModel;
import work.slhaf.partner.api.agent.factory.component.annotation.Init;
import work.slhaf.partner.api.chat.pojo.Message;
import work.slhaf.partner.core.cognition.BlockContent;
import work.slhaf.partner.core.cognition.CognitionCapability;
import work.slhaf.partner.core.cognition.CommunicationBlockContent;
import work.slhaf.partner.core.cognition.ContextBlock;
import work.slhaf.partner.core.cognition.*;
import work.slhaf.partner.runtime.interaction.data.context.PartnerRunningFlowContext;
import javax.xml.parsers.DocumentBuilderFactory;
@@ -105,14 +102,12 @@ public class CommunicationProducer extends AbstractAgentModule.Running<PartnerRu
}
private List<Message> buildChatMessages(PartnerRunningFlowContext runningFlowContext) {
List<BlockContent> communicationBlocks = cognitionCapability.contextWorkspace()
ResolvedContext resolvedContext = cognitionCapability.contextWorkspace()
.resolve(List.of(ContextBlock.VisibleDomain.COMMUNICATION));
List<BlockContent> communicationBlocks = resolvedContext.getBlocks();
List<Message> historyMessages = snapshotConversationMessages();
List<Message> temp = new ArrayList<>(historyMessages.size() + 2);
Message contextMessage = buildContextMessage(communicationBlocks);
if (contextMessage != null) {
temp.add(contextMessage);
}
temp.add(buildContextMessage(communicationBlocks));
temp.addAll(historyMessages);
temp.add(buildInputMessage(runningFlowContext, communicationBlocks));
return temp;
@@ -145,34 +140,13 @@ public class CommunicationProducer extends AbstractAgentModule.Running<PartnerRu
List<BlockContent> contextBlocks = communicationBlocks.stream()
.filter(this::belongsToContextSection)
.toList();
if (contextBlocks.isEmpty()) {
return null;
}
return new Message(Message.Character.USER, buildContextXml(contextBlocks));
return new ResolvedContext(contextBlocks).encodeToContextMessage();
}
private Message buildInputMessage(PartnerRunningFlowContext runningFlowContext, List<BlockContent> communicationBlocks) {
return new Message(Message.Character.USER, buildInputXml(runningFlowContext, communicationBlocks));
}
private String buildContextXml(List<BlockContent> contextBlocks) {
try {
Document document = newDocument();
Element root = document.createElement("context");
document.appendChild(root);
contextBlocks.stream()
.map(BlockContent::encodeToXml)
.forEach(blockElement -> {
root.appendChild(document.importNode(blockElement, true));
});
return toXmlString(document);
} catch (Exception e) {
throw new IllegalStateException("构建 context 区段失败", e);
}
}
private String buildInputXml(PartnerRunningFlowContext runningFlowContext, List<BlockContent> communicationBlocks) {
try {
Document document = newDocument();