ГЛОБАЛЬНЫЙ РЕФАКТОРИНГ АРХИТЕКТУРЫ - Рефакторинг этапов 2.2.1 - фикс деградаций по старым доменам + легкая доводка регрессий перед стартом 3его этапа
This commit is contained in:
@@ -1415,6 +1415,67 @@ function sanitizeGeneratedQuestion(value: string): string {
|
||||
.trim();
|
||||
}
|
||||
|
||||
const AUTOGEN_QUESTION_PLACEHOLDER_PATTERN = /^(?:questions?|вопросы?|список\s+вопросов)$/iu;
|
||||
const AUTOGEN_QUESTION_TAIL_PATTERNS: RegExp[] = [
|
||||
/^(?:без\s+воды|по\s+факту|и\s+коротко|коротко|прям(?:\s+)?сейчас|за\s+весь\s+период|по\s+делу)\??$/iu
|
||||
];
|
||||
|
||||
function stripAutogenQuestionSuffix(value: string): string {
|
||||
return sanitizeGeneratedQuestion(value).replace(/[?!.:,;]+$/u, "").trim();
|
||||
}
|
||||
|
||||
function isAutogenQuestionPlaceholder(value: string): boolean {
|
||||
const core = stripAutogenQuestionSuffix(value).toLowerCase();
|
||||
return core.length > 0 && AUTOGEN_QUESTION_PLACEHOLDER_PATTERN.test(core);
|
||||
}
|
||||
|
||||
function isLikelyAutogenQuestionTail(value: string): boolean {
|
||||
const core = stripAutogenQuestionSuffix(value).toLowerCase();
|
||||
if (!core) {
|
||||
return false;
|
||||
}
|
||||
if (isAutogenQuestionPlaceholder(core)) {
|
||||
return true;
|
||||
}
|
||||
return AUTOGEN_QUESTION_TAIL_PATTERNS.some((pattern) => pattern.test(core));
|
||||
}
|
||||
|
||||
function mergeAutogenQuestionTail(baseQuestion: string, tail: string): string {
|
||||
const base = stripAutogenQuestionSuffix(baseQuestion);
|
||||
const suffix = stripAutogenQuestionSuffix(tail);
|
||||
if (!base) {
|
||||
return suffix ? `${suffix}?` : "";
|
||||
}
|
||||
if (!suffix) {
|
||||
return `${base}?`;
|
||||
}
|
||||
return `${base} ${suffix}?`
|
||||
.replace(/\s+/g, " ")
|
||||
.trim();
|
||||
}
|
||||
|
||||
function normalizeAutogenQuestionCandidates(candidates: string[]): string[] {
|
||||
const normalized: string[] = [];
|
||||
for (const candidate of candidates) {
|
||||
const question = sanitizeGeneratedQuestion(candidate);
|
||||
if (!question) {
|
||||
continue;
|
||||
}
|
||||
if (isAutogenQuestionPlaceholder(question)) {
|
||||
continue;
|
||||
}
|
||||
if (isLikelyAutogenQuestionTail(question) && normalized.length > 0) {
|
||||
const merged = mergeAutogenQuestionTail(normalized[normalized.length - 1], question);
|
||||
if (merged) {
|
||||
normalized[normalized.length - 1] = merged;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
normalized.push(question);
|
||||
}
|
||||
return normalized.filter((item) => item.length > 0);
|
||||
}
|
||||
|
||||
function splitQuestionCandidates(rawText: string): string[] {
|
||||
const normalized = repairAutogenMojibake(rawText).replace(/\r/g, "\n").trim();
|
||||
if (!normalized) return [];
|
||||
@@ -1426,18 +1487,26 @@ function splitQuestionCandidates(rawText: string): string[] {
|
||||
.map((line) => sanitizeGeneratedQuestion(line))
|
||||
.filter((line) => line.length > 0);
|
||||
if (byLines.length > 1) {
|
||||
return byLines;
|
||||
return normalizeAutogenQuestionCandidates(byLines);
|
||||
}
|
||||
|
||||
const questionMarkCount = (unescaped.match(/\?/g) ?? []).length;
|
||||
if (questionMarkCount > 1) {
|
||||
const byQuestion = unescaped
|
||||
.split("?")
|
||||
.map((chunk) => sanitizeGeneratedQuestion(chunk))
|
||||
.filter((chunk) => chunk.length > 0)
|
||||
.map((chunk) => (chunk.endsWith("?") ? chunk : `${chunk}?`));
|
||||
if (byQuestion.length > 1) {
|
||||
return byQuestion;
|
||||
const questionChunks = Array.from(unescaped.matchAll(/[^?]+(?:\?|$)/g))
|
||||
.map((match) => sanitizeGeneratedQuestion(match[0]))
|
||||
.filter((chunk) => chunk.length > 0);
|
||||
if (questionChunks.length > 1) {
|
||||
const canSafelySplit = questionChunks.every(
|
||||
(chunk) =>
|
||||
!isAutogenQuestionPlaceholder(chunk) &&
|
||||
!isLikelyAutogenQuestionTail(chunk) &&
|
||||
sanitizeGeneratedQuestion(chunk).length >= 18
|
||||
);
|
||||
if (canSafelySplit) {
|
||||
return normalizeAutogenQuestionCandidates(
|
||||
questionChunks.map((chunk) => (chunk.endsWith("?") ? chunk : `${chunk}?`))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1445,11 +1514,11 @@ function splitQuestionCandidates(rawText: string): string[] {
|
||||
.map((match) => sanitizeGeneratedQuestion(match[1]))
|
||||
.filter((line) => line.length > 0);
|
||||
if (quoted.length > 1) {
|
||||
return quoted;
|
||||
return normalizeAutogenQuestionCandidates(quoted);
|
||||
}
|
||||
|
||||
const cleaned = sanitizeGeneratedQuestion(unescaped);
|
||||
return cleaned ? [cleaned] : [];
|
||||
return cleaned ? normalizeAutogenQuestionCandidates([cleaned]) : [];
|
||||
}
|
||||
|
||||
function parseAutogenOutputJson(rawText: string): unknown | null {
|
||||
@@ -1496,7 +1565,8 @@ function collectQuestionsFromCandidate(value: unknown, depth = 0): string[] {
|
||||
}
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
return value.flatMap((item) => collectQuestionsFromCandidate(item, depth + 1));
|
||||
const expanded = value.flatMap((item) => collectQuestionsFromCandidate(item, depth + 1));
|
||||
return normalizeAutogenQuestionCandidates(expanded);
|
||||
}
|
||||
|
||||
if (typeof value === "string") {
|
||||
@@ -1549,6 +1619,11 @@ function extractQuestionsFromAutogenOutput(rawText: string): string[] {
|
||||
return collectQuestionsFromCandidate(rawText);
|
||||
}
|
||||
|
||||
export const __autoRunsQuestionTestUtils = {
|
||||
splitQuestionCandidates,
|
||||
extractQuestionsFromAutogenOutput
|
||||
};
|
||||
|
||||
async function generateQwenSeedQuestionsLive(input: {
|
||||
count: number;
|
||||
domain: string | null;
|
||||
|
||||
@@ -73,6 +73,67 @@ function normalizeQuestionChunk(value: string): string {
|
||||
.trim();
|
||||
}
|
||||
|
||||
const RUNTIME_QUESTION_PLACEHOLDER_PATTERN = /^(?:questions?|вопросы?|список\s+вопросов)$/iu;
|
||||
const RUNTIME_QUESTION_TAIL_PATTERNS: RegExp[] = [
|
||||
/^(?:без\s+воды|по\s+факту|и\s+коротко|коротко|прям(?:\s+)?сейчас|за\s+весь\s+период|по\s+делу)\??$/iu
|
||||
];
|
||||
|
||||
function stripQuestionSuffix(value: string): string {
|
||||
return normalizeQuestionChunk(value).replace(/[?!.:,;]+$/u, "").trim();
|
||||
}
|
||||
|
||||
function isRuntimeQuestionPlaceholder(value: string): boolean {
|
||||
const core = stripQuestionSuffix(value).toLowerCase();
|
||||
return core.length > 0 && RUNTIME_QUESTION_PLACEHOLDER_PATTERN.test(core);
|
||||
}
|
||||
|
||||
function isLikelyRuntimeQuestionTail(value: string): boolean {
|
||||
const core = stripQuestionSuffix(value).toLowerCase();
|
||||
if (!core) {
|
||||
return false;
|
||||
}
|
||||
if (isRuntimeQuestionPlaceholder(core)) {
|
||||
return true;
|
||||
}
|
||||
return RUNTIME_QUESTION_TAIL_PATTERNS.some((pattern) => pattern.test(core));
|
||||
}
|
||||
|
||||
function mergeRuntimeQuestionTail(baseQuestion: string, tail: string): string {
|
||||
const base = stripQuestionSuffix(baseQuestion);
|
||||
const suffix = stripQuestionSuffix(tail);
|
||||
if (!base) {
|
||||
return suffix ? `${suffix}?` : "";
|
||||
}
|
||||
if (!suffix) {
|
||||
return `${base}?`;
|
||||
}
|
||||
return `${base} ${suffix}?`
|
||||
.replace(/\s+/g, " ")
|
||||
.trim();
|
||||
}
|
||||
|
||||
function normalizeRuntimeQuestionList(items: string[]): string[] {
|
||||
const normalized: string[] = [];
|
||||
for (const item of items) {
|
||||
const chunk = normalizeQuestionChunk(item);
|
||||
if (!chunk) {
|
||||
continue;
|
||||
}
|
||||
if (isRuntimeQuestionPlaceholder(chunk)) {
|
||||
continue;
|
||||
}
|
||||
if (isLikelyRuntimeQuestionTail(chunk) && normalized.length > 0) {
|
||||
const merged = mergeRuntimeQuestionTail(normalized[normalized.length - 1], chunk);
|
||||
if (merged) {
|
||||
normalized[normalized.length - 1] = merged;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
normalized.push(chunk);
|
||||
}
|
||||
return normalized.filter((item) => item.length > 0);
|
||||
}
|
||||
|
||||
function splitQuestionCandidate(raw: string): string[] {
|
||||
const normalized = String(raw ?? "").replace(/\r/g, "\n").trim();
|
||||
if (!normalized) {
|
||||
@@ -87,18 +148,32 @@ function splitQuestionCandidate(raw: string): string[] {
|
||||
|
||||
const chunks: string[] = [];
|
||||
for (const line of source) {
|
||||
const normalizedLine = normalizeQuestionChunk(line);
|
||||
if (!normalizedLine || isRuntimeQuestionPlaceholder(normalizedLine)) {
|
||||
continue;
|
||||
}
|
||||
const questionLike = Array.from(line.matchAll(/[^?]+(?:\?|$)/g))
|
||||
.map((match) => normalizeQuestionChunk(match[0]))
|
||||
.filter((item) => item.length > 0);
|
||||
if (questionLike.length > 1) {
|
||||
for (const item of questionLike) {
|
||||
chunks.push(item.endsWith("?") ? item : `${item}?`);
|
||||
const canSafelySplit = questionLike.every(
|
||||
(item) =>
|
||||
!isRuntimeQuestionPlaceholder(item) &&
|
||||
!isLikelyRuntimeQuestionTail(item) &&
|
||||
normalizeQuestionChunk(item).length >= 18
|
||||
);
|
||||
if (canSafelySplit) {
|
||||
for (const item of questionLike) {
|
||||
chunks.push(item.endsWith("?") ? item : `${item}?`);
|
||||
}
|
||||
} else {
|
||||
chunks.push(normalizedLine);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
chunks.push(normalizeQuestionChunk(line));
|
||||
chunks.push(normalizedLine);
|
||||
}
|
||||
return chunks.filter((item) => item.length > 0);
|
||||
return normalizeRuntimeQuestionList(chunks);
|
||||
}
|
||||
|
||||
function normalizeRuntimeQuestions(value: unknown): string[] {
|
||||
@@ -109,7 +184,7 @@ function normalizeRuntimeQuestions(value: unknown): string[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
const expanded = raw.flatMap((item) => splitQuestionCandidate(item));
|
||||
const expanded = normalizeRuntimeQuestionList(raw.flatMap((item) => splitQuestionCandidate(item)));
|
||||
const deduped: string[] = [];
|
||||
const seen = new Set<string>();
|
||||
for (const item of expanded) {
|
||||
@@ -122,6 +197,11 @@ function normalizeRuntimeQuestions(value: unknown): string[] {
|
||||
return deduped;
|
||||
}
|
||||
|
||||
export const __evalRouteTestUtils = {
|
||||
splitQuestionCandidate,
|
||||
normalizeRuntimeQuestions
|
||||
};
|
||||
|
||||
function normalizeCaseIds(value: unknown): string[] | undefined {
|
||||
if (!Array.isArray(value)) {
|
||||
return undefined;
|
||||
|
||||
Reference in New Issue
Block a user