mirror of
https://gitee.com/mateos/mateclaw.git
synced 2026-09-13 03:13:41 +08:00
feat(wiki): clean conversational preamble and code fences from transformation output
This commit is contained in:
parent
f04ea58c8d
commit
62c9776b01
1
.gitignore
vendored
1
.gitignore
vendored
@ -98,7 +98,6 @@ CLAUDE.md
|
||||
|
||||
# Codex CLI local artifacts
|
||||
.codex/
|
||||
.superpowers/
|
||||
|
||||
# Sync tooling local state (generated each run; report is intentionally tracked)
|
||||
scripts/.*-sync-state.json
|
||||
|
||||
@ -144,12 +144,16 @@ public class WikiTransformationExecutor {
|
||||
|
||||
ChatResponse resp = chatModel.call(new Prompt(List.of(
|
||||
new SystemMessage(systemPrompt), new UserMessage(userPrompt))));
|
||||
String output = (resp == null || resp.getResult() == null
|
||||
String rawOutput = (resp == null || resp.getResult() == null
|
||||
|| resp.getResult().getOutput() == null)
|
||||
? null : resp.getResult().getOutput().getText();
|
||||
if (output == null || output.isBlank()) {
|
||||
if (rawOutput == null || rawOutput.isBlank()) {
|
||||
throw new IllegalStateException("LLM returned empty output");
|
||||
}
|
||||
String output = cleanLlmOutput(rawOutput);
|
||||
if (output.isBlank()) {
|
||||
throw new IllegalStateException("LLM output was empty after cleanup");
|
||||
}
|
||||
// Honour a mid-flight cancel: the cancel endpoint flipped the run
|
||||
// row to 'cancelled' while the LLM was still working. Drop the
|
||||
// output and stop here rather than overwrite the cancelled state.
|
||||
@ -252,6 +256,51 @@ public class WikiTransformationExecutor {
|
||||
return (t == null || t.isBlank()) ? ("raw#" + raw.getId()) : t;
|
||||
}
|
||||
|
||||
/** Recognises the conversational openers LLMs sometimes prepend even when
|
||||
* the system prompt told them not to. Lines matching this pattern at the
|
||||
* very start of the output are dropped. */
|
||||
private static final java.util.regex.Pattern PREAMBLE_PATTERN =
|
||||
java.util.regex.Pattern.compile(
|
||||
"^\\s*(以下是|下面是|这是|根据您的要求|Sure(?:!|,)?|Of course[!,]?|Here(?:'s| is| are)|Certainly[!,]?|Got it[!,]?)[^\\n]*[::][^\\n]*\\n+",
|
||||
java.util.regex.Pattern.CASE_INSENSITIVE);
|
||||
|
||||
/**
|
||||
* Normalise raw LLM output before persisting:
|
||||
* <ul>
|
||||
* <li>strip an outer markdown / language code fence (```markdown ... ``` or ``` ... ```)</li>
|
||||
* <li>drop a conversational opener line ending with a colon</li>
|
||||
* <li>trim whitespace</li>
|
||||
* </ul>
|
||||
* Conservative — only trims when the heuristic match is unambiguous,
|
||||
* because over-trimming on a structured response would corrupt content.
|
||||
*/
|
||||
static String cleanLlmOutput(String text) {
|
||||
if (text == null) return "";
|
||||
String result = text.trim();
|
||||
|
||||
// Outer code fence ```lang? ... ```
|
||||
if (result.startsWith("```")) {
|
||||
int firstNewline = result.indexOf('\n');
|
||||
if (firstNewline > 0 && result.endsWith("```")) {
|
||||
String header = result.substring(3, firstNewline).trim();
|
||||
// Only strip when the header is empty or looks like a language tag
|
||||
// (markdown / md / json / yaml / text / plaintext) — never strip
|
||||
// when the LLM used ``` as actual fenced content inside.
|
||||
if (header.isEmpty() || header.matches("(?i)markdown|md|text|plaintext|json|yaml|yml|html?")) {
|
||||
result = result.substring(firstNewline + 1, result.length() - 3).trim();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Conversational opener line ending with a colon, followed by content.
|
||||
java.util.regex.Matcher m = PREAMBLE_PATTERN.matcher(result);
|
||||
if (m.find()) {
|
||||
result = result.substring(m.end()).trim();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// ==================== Save-as-page ====================
|
||||
|
||||
/**
|
||||
|
||||
Loading…
Reference in New Issue
Block a user