feat: tweaking of newsletter prompt
This commit is contained in:
30
utils/anthropic/client.ts
Normal file
30
utils/anthropic/client.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import Anthropic from '@anthropic-ai/sdk';
|
||||
import { BaseTool } from './tool';
|
||||
|
||||
export async function getMessage<T>(text: string, tool: BaseTool) {
|
||||
const anthropic = new Anthropic({
|
||||
apiKey: process.env.ANTHROPIC_API_KEY
|
||||
});
|
||||
|
||||
console.info('Anthropic request with text: ', text);
|
||||
|
||||
const response = await anthropic.messages.create({
|
||||
model: 'claude-3-5-sonnet-20241022',
|
||||
max_tokens: 2048,
|
||||
messages: [{ role: 'user', content: text }],
|
||||
tools: [tool]
|
||||
});
|
||||
|
||||
console.info('Anthropic response: ', response);
|
||||
|
||||
try {
|
||||
const data = response.content as [
|
||||
{ type: string; text: string },
|
||||
{ type: string; input: object } // object of type V
|
||||
];
|
||||
|
||||
return data[1].input as T;
|
||||
} catch (error) {
|
||||
throw Error(JSON.stringify(error));
|
||||
}
|
||||
}
|
||||
28
utils/anthropic/summarize.ts
Normal file
28
utils/anthropic/summarize.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { getMessage } from './client';
|
||||
import { NewsType } from '../validationSchemas';
|
||||
import { NewsletterTool, newsletterTool } from './tool';
|
||||
|
||||
export async function summirize(news: NewsType[]) {
|
||||
const newsInput = news
|
||||
.map(n => `TITLE: ${n.title}, CONTENT: ${n.text}, LINK: ${n.url}`)
|
||||
.join('\n\n');
|
||||
|
||||
const promptSetup =
|
||||
"You are a tech journalist with a technology degree and background. Create a tech newsletter from the following list of posts from an online forum. Use the NewsletterTool to structure your response with the following requirements:\n\n1. TITLE:\n- Create a title that is 40-50 characters long\n- Capture the most significant themes or developments\n- Use engaging but professional language\n\n2. CONTENT:\nSummarize the following list of posts from an online forum as a TL;DR (Too Long; Didn't Read) summary. Your summary should:\n1. Be 300-400 words long (not counting the urls)\n2. Structure the content in 2-3 short paragraphs, with each paragraph focusing on a specific theme or technology area\n3. Start with the 2-3 most significant or impactful news items in the first paragraph\n4. Use HTML paragraph tags (<p>) to separate paragraphs for better readability\n5. Use a tone that is informative and slightly enthusiastic, aimed at tech-savvy general readers\n6. Incorporate links as follows, including at most 3-4 words: <a href='[LINK]' target='_blank' rel='noopener noreferrer'>[linked text]</a>\n7. Each mentioned news item must include its own url link\n\n3. FOCUS:\nEnd with a forward-looking assessment of the key developments and trends emerging from these news items. Consider their potential impact on the tech landscape and any implications for future developments. Keep this section concise while maintaining an analytical perspective that helps readers understand what to watch for in the coming weeks and months.\n\nUse the NewsletterTool to provide your response with these three components.\n\nThe news items are structured as follows:\n\nTITLE: <title>\nCONTENT: <content>\nLINK: <link>\n\nPlease analyze and summarize the following news:";
|
||||
|
||||
try {
|
||||
const { title, content, focus } = await getMessage<NewsletterTool>(
|
||||
promptSetup + newsInput,
|
||||
newsletterTool
|
||||
);
|
||||
|
||||
return {
|
||||
title,
|
||||
content,
|
||||
focus
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Error in summarize:', error);
|
||||
throw Error(JSON.stringify(error));
|
||||
}
|
||||
}
|
||||
37
utils/anthropic/tool.ts
Normal file
37
utils/anthropic/tool.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
export interface BaseTool {
|
||||
readonly name: string;
|
||||
readonly input_schema: {
|
||||
readonly type: 'object';
|
||||
readonly properties: Record<string, unknown>;
|
||||
readonly required?: readonly string[];
|
||||
readonly description?: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface NewsletterTool {
|
||||
title: string;
|
||||
content: string;
|
||||
focus: string;
|
||||
}
|
||||
|
||||
export const newsletterTool: BaseTool = {
|
||||
name: 'NewsletterTool' as const,
|
||||
input_schema: {
|
||||
type: 'object' as const,
|
||||
description: 'Newsletter',
|
||||
properties: {
|
||||
title: {
|
||||
type: 'string' as const,
|
||||
description: 'The title of the newsletter'
|
||||
},
|
||||
content: {
|
||||
type: 'string' as const,
|
||||
description: 'The main content of the newsletter'
|
||||
},
|
||||
focus: {
|
||||
type: 'string' as const,
|
||||
description: 'The text of the focus segment'
|
||||
}
|
||||
}
|
||||
}
|
||||
} as const;
|
||||
@@ -1,19 +0,0 @@
|
||||
import Anthropic from '@anthropic-ai/sdk';
|
||||
|
||||
export async function getMessage(text: string) {
|
||||
const anthropic = new Anthropic({
|
||||
apiKey: process.env.ANTHROPIC_API_KEY
|
||||
});
|
||||
|
||||
console.log('Anthropic request with text: ', text);
|
||||
|
||||
const response = await anthropic.messages.create({
|
||||
model: 'claude-3-5-sonnet-20240620',
|
||||
max_tokens: 1024,
|
||||
messages: [{ role: 'user', content: text }]
|
||||
});
|
||||
|
||||
console.log('Anthropic response: ', response);
|
||||
|
||||
return response;
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
function extractMainTopic(summary: string): string {
|
||||
const firstParaMatch = summary.match(/<p>(.*?)<\/p>/);
|
||||
if (!firstParaMatch) return 'tech updates';
|
||||
|
||||
const firstPara = firstParaMatch[1];
|
||||
|
||||
const cleanText = firstPara
|
||||
.replace(/<[^>]*>/g, '')
|
||||
.replace(/\s+/g, ' ')
|
||||
.replace(/[,.]+/g, ' ')
|
||||
.trim();
|
||||
|
||||
const techAreas = [
|
||||
{
|
||||
name: 'AI',
|
||||
pattern: /\b(AI|artificial intelligence|machine learning|ML|GPT|LLM)\b/i,
|
||||
preserveCase: true
|
||||
},
|
||||
{
|
||||
name: 'security',
|
||||
pattern: /\b(security|cyber|hack|privacy|breach)\b/i
|
||||
},
|
||||
{
|
||||
name: 'Web3',
|
||||
pattern: /\b(blockchain|crypto|web3|NFT|token|ethereum|bitcoin)\b/i,
|
||||
preserveCase: true
|
||||
},
|
||||
{
|
||||
name: 'cloud',
|
||||
pattern: /\b(cloud|AWS|Azure|serverless|containerization|kubernetes)\b/i
|
||||
},
|
||||
{
|
||||
name: 'mobile',
|
||||
pattern: /\b(mobile|iOS|Android|app|smartphone)\b/i
|
||||
},
|
||||
{
|
||||
name: 'development',
|
||||
pattern: /\b(developer|programming|code|software|development)\b/i
|
||||
}
|
||||
];
|
||||
|
||||
for (const area of techAreas) {
|
||||
if (area.pattern.test(cleanText)) {
|
||||
return area.preserveCase ? area.name : area.name.toLowerCase();
|
||||
}
|
||||
}
|
||||
|
||||
const words = cleanText
|
||||
.split(' ')
|
||||
.filter(
|
||||
word =>
|
||||
word.length > 2 &&
|
||||
!/^(and|the|in|of|at|by|for)$/i.test(word) &&
|
||||
!/[,.]/.test(word)
|
||||
)
|
||||
.slice(0, 2)
|
||||
.join(' ');
|
||||
|
||||
return words.toLowerCase() || 'tech updates';
|
||||
}
|
||||
|
||||
export default function getNewsletterSubject(summary: string) {
|
||||
const topic = extractMainTopic(summary);
|
||||
const title =
|
||||
topic === 'tech updates'
|
||||
? 'Today in tech updates'
|
||||
: `Today in tech: ${topic}`;
|
||||
|
||||
return title;
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
import { getMessage } from './anthropicClient';
|
||||
import { NewsType } from './validationSchemas';
|
||||
|
||||
export async function summirize(news: NewsType[]) {
|
||||
const newsInput = news
|
||||
.map(n => `TITLE: ${n.title}, CONTENT: ${n.text}, LINK: ${n.url}`)
|
||||
.join('\n\n');
|
||||
|
||||
const promptSetup =
|
||||
'You are a tech journalist with a technology degree and background. Summarize the following list of posts from an online forum as a TL;DR (Too Long; Didn't Read) summary. Your summary should:\n\n1. Be 300-400 words long (not counting the urls).\n\n2. Structure the content in 2-3 short paragraphs, with each paragraph focusing on a specific theme or technology area.\n\n3. Start with the 2-3 most significant or impactful news items in the first paragraph.\n\n4. Use HTML paragraph tags (<p>) to separate paragraphs for better readability.\n\n5. Use a tone that is informative and slightly enthusiastic, aimed at tech-savvy general readers.\n\n6. Incorporate links as follows, including at most 3-4 words: <a href='[LINK]' target='_blank' rel='noopener noreferrer'>[linked text]</a>.\n\n7. Each mentioned news item must include its own url link.\n\n8. End with a section wrapped in a div with inline styles: <div style='margin-top: 24px; padding: 20px; background: #F8FAFC; border-left: 3px solid #386FA4; border-radius: 4px;'>. Inside this div, start with an <h3 style='margin: 0 0 12px 0; color: #386FA4; font-size: 18px; font-weight: 600;'>What to Watch</h3> followed by a paragraph highlighting emerging trends or developments to follow.</div>\n\nFocus on conveying the key points and their potential impact on the tech landscape. Your response should consist of the summary only.\n\nThe news items are structured as follows:\n\nTITLE: <title>\nCONTENT: <content>\nLINK: <link>\n\nPlease summarize the following news:';
|
||||
try {
|
||||
const response = await getMessage(promptSetup + newsInput);
|
||||
|
||||
const summary = response.content[0] as { text: string };
|
||||
|
||||
return summary.text;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return '';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user