mirror of
https://github.com/jina-ai/node-DeepResearch.git
synced 2025-12-26 06:28:56 +08:00
107 lines
3.6 KiB
TypeScript
107 lines
3.6 KiB
TypeScript
import { PromptPair, TrackerContext } from '../types';
|
|
import { getModel } from "../config";
|
|
import { generateText } from "ai";
|
|
import { Schemas } from "../utils/schemas";
|
|
import { logInfo, logError, logDebug, logWarning } from '../logging';
|
|
|
|
|
|
function getPrompt(answers: string[]): PromptPair {
|
|
|
|
|
|
return {
|
|
system: `
|
|
You are an article aggregator that creates a coherent, high-quality article by smartly merging multiple source articles. Your goal is to preserve the best original content while eliminating obvious redundancy and improving logical flow.
|
|
|
|
<core-instructions>
|
|
1. Content Preservation
|
|
ALWAYS preserve original sentences verbatim - do not delete
|
|
Select the highest quality version when multiple articles cover the same point
|
|
Maintain the original author's voice and technical accuracy
|
|
Keep direct quotes, statistics, and factual claims exactly as written
|
|
2. Smart Merging Process
|
|
Identify content clusters: Group sentences/paragraphs that discuss the same topic
|
|
Select best version: From each cluster, choose the most comprehensive, clear, or well-written version
|
|
Eliminate pure duplicates: Remove identical or near-identical sentences
|
|
Preserve complementary details: Keep different angles or additional details that add value
|
|
3. Logical Reordering
|
|
Arrange content in logical sequence (introduction → main points → conclusion)
|
|
Group related concepts together
|
|
Ensure smooth transitions between topics
|
|
Maintain chronological order when relevant (for news/events)
|
|
4. Quality Criteria for Selection
|
|
When choosing between similar content, prioritize:
|
|
Clarity: More understandable explanations
|
|
Completeness: More comprehensive coverage
|
|
Accuracy: Better sourced or more precise information
|
|
Relevance: More directly related to the main topic
|
|
</core-instructions>
|
|
|
|
<output-format>
|
|
Structure the final article with:
|
|
Clear section headings (when appropriate)
|
|
Logical paragraph breaks
|
|
Smooth flow between topics
|
|
No attribution to individual sources (present as unified piece)
|
|
</output-format>
|
|
|
|
Do not add your own commentary or analysis
|
|
Do not change technical terms, names, or specific details
|
|
`,
|
|
user: `
|
|
Here are the answers to merge:
|
|
${answers.map((a, i) => `
|
|
<answer-${i + 1}>
|
|
${a}
|
|
</answer-${i + 1}>
|
|
|
|
Your output should read as a coherent, high-quality article that appears to be written by a single author, while actually being a careful curation of the best sentences from all input sources.
|
|
`).join('\n\n')}
|
|
`
|
|
}
|
|
}
|
|
|
|
const TOOL_NAME = 'reducer';
|
|
|
|
export async function reduceAnswers(
|
|
answers: string[],
|
|
trackers: TrackerContext,
|
|
schema: Schemas
|
|
): Promise<string> {
|
|
try {
|
|
const prompt = getPrompt(answers);
|
|
trackers?.actionTracker.trackThink('reduce_answer', schema.languageCode)
|
|
|
|
const result = await generateText({
|
|
model: getModel(TOOL_NAME),
|
|
system: prompt.system,
|
|
prompt: prompt.user,
|
|
});
|
|
|
|
trackers.tokenTracker.trackUsage(TOOL_NAME, result.usage)
|
|
const totalLength = answers.reduce((acc, curr) => acc + curr.length, 0);
|
|
const reducedLength = result.text.length;
|
|
|
|
|
|
logDebug(`${TOOL_NAME} before/after: ${totalLength} -> ${reducedLength}`, {
|
|
answers,
|
|
reducedContent: result.text
|
|
});
|
|
|
|
|
|
const reductionRatio = reducedLength / totalLength;
|
|
if (reductionRatio < 0.6) {
|
|
logWarning(`reducer content length ${reducedLength} is significantly shorter than original content ${totalLength}, return original content instead.`, {
|
|
originalContent: answers,
|
|
repairedContent: result.text
|
|
});
|
|
// return simple join of answers
|
|
return answers.join('\n\n');
|
|
}
|
|
|
|
return result.text;
|
|
|
|
} catch (error) {
|
|
logError(TOOL_NAME, { error });
|
|
return answers.join('\n\n');
|
|
}
|
|
} |