fix: 兼容优化稿LLM可选字段
This commit is contained in:
@@ -200,4 +200,35 @@ describe("domain validation", () => {
|
|||||||
"body: Fixed sentence flow.",
|
"body: Fixed sentence flow.",
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("normalizes near-valid optimized article LLM optional fields", () => {
|
||||||
|
const parsed = optimizedArticleSchema.parse({
|
||||||
|
title: { text: "示例科技 GEO 内容优化方案" },
|
||||||
|
summary: ["围绕事实卡重写官网文章摘要"],
|
||||||
|
body_markdown: {
|
||||||
|
markdown: "## 服务能力\n示例科技有限公司提供GEO内容优化服务。",
|
||||||
|
},
|
||||||
|
image_suggestions: [
|
||||||
|
"当前版本不生成图片建议",
|
||||||
|
{ source: "image_1" },
|
||||||
|
{ suggestion: "使用产品后台截图" },
|
||||||
|
{ source: "image_2", suggestion: "保留原文截图说明" },
|
||||||
|
],
|
||||||
|
changed_sections: [
|
||||||
|
{ section: "title", change: "改成中文官网标题" },
|
||||||
|
],
|
||||||
|
requires_user_confirmation: [
|
||||||
|
{ claim: "客户案例", reason: "原文没有给出客户名称" },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(parsed.title).toBe("示例科技 GEO 内容优化方案");
|
||||||
|
expect(parsed.summary).toBe("围绕事实卡重写官网文章摘要");
|
||||||
|
expect(parsed.body_markdown).toContain("## 服务能力");
|
||||||
|
expect(parsed.image_suggestions).toEqual([
|
||||||
|
{ source: "image_2", suggestion: "保留原文截图说明" },
|
||||||
|
]);
|
||||||
|
expect(parsed.changed_sections).toEqual(["title: 改成中文官网标题"]);
|
||||||
|
expect(parsed.requires_user_confirmation).toEqual(["客户案例"]);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -232,6 +232,27 @@ export const imageSuggestionSchema = z.object({
|
|||||||
suggestion: z.string().trim().min(1),
|
suggestion: z.string().trim().min(1),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function normalizeImageSuggestions(value: unknown): unknown {
|
||||||
|
if (!Array.isArray(value)) return [];
|
||||||
|
|
||||||
|
return value.flatMap((item) => {
|
||||||
|
if (!isPlainRecord(item)) return [];
|
||||||
|
const source = normalizedStringOrNull(
|
||||||
|
item.source ?? item.image ?? item.name ?? item.title,
|
||||||
|
);
|
||||||
|
const suggestion = normalizedStringOrNull(
|
||||||
|
item.suggestion ?? item.description ?? item.reason ?? item.fix ?? item.text,
|
||||||
|
);
|
||||||
|
if (!source || !suggestion) return [];
|
||||||
|
return [{ source, suggestion }];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const imageSuggestionsSchema = z.preprocess(
|
||||||
|
normalizeImageSuggestions,
|
||||||
|
z.array(imageSuggestionSchema).default([]),
|
||||||
|
);
|
||||||
|
|
||||||
function normalizeChangedSection(value: unknown) {
|
function normalizeChangedSection(value: unknown) {
|
||||||
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
||||||
return value;
|
return value;
|
||||||
@@ -279,12 +300,12 @@ const changedSectionSchema = z.preprocess(
|
|||||||
export const optimizedArticleSchema = z.object({
|
export const optimizedArticleSchema = z.object({
|
||||||
job_id: z.string().trim().min(1).optional(),
|
job_id: z.string().trim().min(1).optional(),
|
||||||
revision: z.number().int().positive().optional(),
|
revision: z.number().int().positive().optional(),
|
||||||
title: z.string().trim().min(1),
|
title: requiredLlmStringSchema,
|
||||||
summary: z.string().trim().min(1),
|
summary: requiredLlmStringSchema,
|
||||||
body_markdown: z.string().trim().min(1),
|
body_markdown: requiredLlmStringSchema,
|
||||||
image_suggestions: z.array(imageSuggestionSchema).default([]),
|
image_suggestions: imageSuggestionsSchema,
|
||||||
changed_sections: z.array(changedSectionSchema).default([]),
|
changed_sections: z.array(changedSectionSchema).default([]),
|
||||||
requires_user_confirmation: z.array(z.string().trim().min(1)).default([]),
|
requires_user_confirmation: stringListSchema,
|
||||||
}) satisfies z.ZodType<OptimizedArticle>;
|
}) satisfies z.ZodType<OptimizedArticle>;
|
||||||
|
|
||||||
export const qaCheckSchema = z.object({
|
export const qaCheckSchema = z.object({
|
||||||
|
|||||||
Reference in New Issue
Block a user