feat: 完成工作流多文件文档解析闭环
- 支持文档解析节点批量解析并收口为 documents 轻量输出 - 收口引用树、节点输出展示与旧工作流固定输出兼容 - 修复共享按钮点击事件,恢复多个节点加号交互
This commit is contained in:
@@ -16,7 +16,9 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import com.sun.net.httpserver.HttpServer;
|
||||
|
||||
@@ -211,6 +213,56 @@ public class DocNodeFileContentExtractorTest {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证多文件输入会按顺序返回逐文件结果。
|
||||
*/
|
||||
@Test
|
||||
public void shouldExtractDocumentsForMultipleFiles() {
|
||||
RecordingDocumentParseBridgeService bridgeService = new RecordingDocumentParseBridgeService();
|
||||
DocNodeFileContentExtractor extractor = new DocNodeFileContentExtractor(
|
||||
bridgeService,
|
||||
new FakeFileStorageService(),
|
||||
new FakeReaderManager("plain text")
|
||||
);
|
||||
|
||||
List<DocNodeFileContentExtractor.DocExtractedDocument> documents = extractor.extractDocuments(Arrays.asList(
|
||||
buildFileValue("demo.pdf", "/files/demo.pdf", "application/pdf"),
|
||||
buildFileValue("note.txt", "/files/note.txt", "text/plain")
|
||||
));
|
||||
|
||||
Assert.assertEquals(2, documents.size());
|
||||
Assert.assertEquals("demo.pdf", documents.get(0).getFileName());
|
||||
Assert.assertEquals("# parsed", documents.get(0).getContent());
|
||||
Assert.assertEquals("note.txt", documents.get(1).getFileName());
|
||||
Assert.assertEquals("plain text", documents.get(1).getContent());
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证多文件中任一文件失败时会暴露文件名。
|
||||
*/
|
||||
@Test
|
||||
public void shouldExposeFileNameWhenMultipleDocumentsFail() {
|
||||
RecordingDocumentParseBridgeService bridgeService = new RecordingDocumentParseBridgeService();
|
||||
bridgeService.response.setPreferredText(null);
|
||||
bridgeService.response.setMarkdown(null);
|
||||
bridgeService.response.setPlainText(null);
|
||||
DocNodeFileContentExtractor extractor = new DocNodeFileContentExtractor(
|
||||
bridgeService,
|
||||
new FakeFileStorageService(),
|
||||
new FakeReaderManager("plain text")
|
||||
);
|
||||
|
||||
try {
|
||||
extractor.extractDocuments(Arrays.asList(
|
||||
buildFileValue("broken.pdf", "/files/broken.pdf", "application/pdf"),
|
||||
buildFileValue("note.txt", "/files/note.txt", "text/plain")
|
||||
));
|
||||
Assert.fail("expected BusinessException");
|
||||
} catch (BusinessException e) {
|
||||
Assert.assertEquals("文件解析失败(broken.pdf): 文档解析结果为空", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, Object> buildFileValue(String fileName, String filePath, String contentType) {
|
||||
Map<String, Object> value = new HashMap<String, Object>();
|
||||
value.put("fileName", fileName);
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package tech.easyflow.ai.node;
|
||||
|
||||
import com.easyagents.flow.core.chain.Parameter;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* {@link DocNode} 单元测试。
|
||||
*/
|
||||
public class DocNodeTest {
|
||||
|
||||
/**
|
||||
* 历史工作流若改过输出名,仍应按固定输出槽位顺序映射运行态结果键。
|
||||
*
|
||||
* @throws Exception 反射调用失败
|
||||
*/
|
||||
@Test
|
||||
public void shouldResolveOutputKeyMappingByOutputOrder() throws Exception {
|
||||
DocNode node = new DocNode();
|
||||
node.setOutputDefs(Arrays.asList(
|
||||
parameter("documentItems")
|
||||
));
|
||||
|
||||
Method method = DocNode.class.getDeclaredMethod("resolveOutputKeyMapping");
|
||||
method.setAccessible(true);
|
||||
Map<String, String> mapping = (Map<String, String>) method.invoke(node);
|
||||
|
||||
Assert.assertEquals("documentItems", mapping.get("documents"));
|
||||
}
|
||||
|
||||
private static Parameter parameter(String name) {
|
||||
Parameter parameter = new Parameter();
|
||||
parameter.setName(name);
|
||||
return parameter;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user