mirror of
https://gitee.com/mateos/mateclaw.git
synced 2026-09-13 03:13:41 +08:00
feat(wiki): inject KB pageType profile into the batch-create prompt
This commit is contained in:
parent
bea48bcf89
commit
b50e384e0d
@ -10,6 +10,7 @@ import vip.mate.wiki.model.WikiPageTypeProfileEntity;
|
||||
import vip.mate.wiki.repository.WikiPageTypeProfileMapper;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
@ -89,6 +90,35 @@ public class WikiPageTypeProfileService {
|
||||
return resolveProfile(kbId).getPageTypes().keySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the KB's allowed page types as a prompt fragment, one per line
|
||||
* with description and required-metadata hints, e.g.
|
||||
* {@code - episode: a dated event (required metadata: event_type, event_date)}.
|
||||
* Injected into the route / batch-create prompts so the LLM only emits
|
||||
* types the KB recognises.
|
||||
*/
|
||||
public String describeForPrompt(Long kbId) {
|
||||
WikiPageTypeProfile profile = resolveProfile(kbId);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
profile.getPageTypes().forEach((name, def) -> {
|
||||
sb.append("- ").append(name);
|
||||
if (def != null && def.getDescription() != null && !def.getDescription().isBlank()) {
|
||||
sb.append(": ").append(def.getDescription().trim());
|
||||
}
|
||||
if (def != null && def.getSchema() != null) {
|
||||
java.util.List<String> required = def.getSchema().entrySet().stream()
|
||||
.filter(e -> e.getValue() != null && e.getValue().isRequired())
|
||||
.map(Map.Entry::getKey)
|
||||
.toList();
|
||||
if (!required.isEmpty()) {
|
||||
sb.append(" (required metadata: ").append(String.join(", ", required)).append(")");
|
||||
}
|
||||
}
|
||||
sb.append('\n');
|
||||
});
|
||||
return sb.toString().trim();
|
||||
}
|
||||
|
||||
/** The enabled profile row for a KB, or {@code null} when none configured. */
|
||||
public WikiPageTypeProfileEntity findEnabledRow(Long kbId) {
|
||||
if (kbId == null) {
|
||||
|
||||
@ -62,6 +62,14 @@ public class WikiProcessingService {
|
||||
private final WikiCitationService citationService;
|
||||
private final org.springframework.context.ApplicationEventPublisher eventPublisher;
|
||||
|
||||
/**
|
||||
* Optional KB pageType profile. Field-injected (not a constructor arg) so
|
||||
* existing instantiations are unaffected; when absent the batch-create
|
||||
* prompt falls back to the legacy hardcoded pageType enum.
|
||||
*/
|
||||
@org.springframework.beans.factory.annotation.Autowired(required = false)
|
||||
private vip.mate.wiki.profile.WikiPageTypeProfileService pageTypeProfileService;
|
||||
|
||||
/**
|
||||
* Read-the-failover-chain handle. Optional so the existing constructors and
|
||||
* lazy-mode tests don't have to thread a new dependency. When null, the
|
||||
@ -1065,6 +1073,16 @@ public class WikiProcessingService {
|
||||
metasJson.append("]");
|
||||
|
||||
String batchSystem = PromptLoader.loadPrompt("wiki/batch-create-system");
|
||||
if (pageTypeProfileService != null) {
|
||||
// Inject the KB's allowed page types so the LLM only emits types
|
||||
// the profile recognises. Default-profile KBs get the same list
|
||||
// as the previous hardcoded enum, so behaviour is unchanged.
|
||||
batchSystem = batchSystem.replace("{allowed_page_types}",
|
||||
pageTypeProfileService.describeForPrompt(kbId));
|
||||
} else {
|
||||
batchSystem = batchSystem.replace("{allowed_page_types}",
|
||||
"concept / person / place / event / technology / organization / product / term / process / other");
|
||||
}
|
||||
String batchUserTemplate = PromptLoader.loadPrompt("wiki/batch-create-user");
|
||||
String docMapSection = buildDocumentMapSection(documentMap);
|
||||
String batchUser = batchUserTemplate
|
||||
|
||||
@ -50,4 +50,8 @@
|
||||
- `title`:与 metadata 保持一致;如有更精确的描述可微调
|
||||
- `content`:完整 markdown 正文
|
||||
- `summary`:一段话简短摘要
|
||||
- `page_type`:页面类型,从以下值中选一个:concept / person / place / event / technology / organization / product / term / process / other
|
||||
- `page_type`:页面类型,从下面"允许的页面类型"列表中选一个;都不合适时选 concept。
|
||||
- `metadata`(可选):与所选 page_type 对应的结构化字段对象,只输出该类型声明的字段(带"required metadata"标注的字段应尽量补全)。
|
||||
|
||||
允许的页面类型:
|
||||
{allowed_page_types}
|
||||
|
||||
@ -79,4 +79,29 @@ class WikiPageTypeProfileServiceTest {
|
||||
assertEquals("concept", service.normalizePageType(1L, "made-up-type"));
|
||||
assertEquals("concept", service.normalizePageType(1L, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void describeForPrompt_defaultProfile_listsBuiltInTypes() {
|
||||
when(mapper.selectOne(any())).thenReturn(null);
|
||||
String fragment = service.describeForPrompt(1L);
|
||||
assertTrue(fragment.contains("- concept"), fragment);
|
||||
assertTrue(fragment.contains("- person"), fragment);
|
||||
assertTrue(fragment.contains("- other"), fragment);
|
||||
}
|
||||
|
||||
@Test
|
||||
void describeForPrompt_customProfile_showsRequiredMetadata() {
|
||||
WikiPageTypeProfileEntity row = new WikiPageTypeProfileEntity();
|
||||
row.setKbId(1L);
|
||||
row.setEnabled(1);
|
||||
row.setConfigJson("{\"pageTypes\":{\"episode\":{\"description\":\"a dated event\","
|
||||
+ "\"schema\":{\"event_date\":{\"type\":\"date\",\"required\":true},"
|
||||
+ "\"note\":{\"type\":\"string\",\"required\":false}}}}}");
|
||||
when(mapper.selectOne(any())).thenReturn(row);
|
||||
|
||||
String fragment = service.describeForPrompt(1L);
|
||||
assertTrue(fragment.contains("- episode: a dated event"), fragment);
|
||||
assertTrue(fragment.contains("required metadata: event_date"), fragment);
|
||||
assertFalse(fragment.contains("note"), fragment); // optional field not listed as required
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user