// Helper function to process a single PDF
const processPdf = wrapTraced(
async (pdfFile: { filename: string; url: string }) => {
console.log(`Processing ${pdfFile.filename}...`);
// Fetch and encode the PDF file from URL (with error handling)
let pdfData: Buffer;
let base64String: string;
try {
const response = await fetch(pdfFile.url);
if (!response.ok) {
throw new Error(`HTTP ${response.status} ${response.statusText}`);
}
const arrayBuffer = await response.arrayBuffer();
pdfData = Buffer.from(arrayBuffer);
base64String = pdfData.toString("base64");
} catch (err: any) {
console.error(`Failed to download ${pdfFile.url}:`, err);
return; // Skip this PDF and continue with the next
}
const userPrompt = "Please analyze this earnings call transcript";
const rootSpan = currentSpan();
rootSpan.setAttributes({ name: pdfFile.filename });
const rootSpanSlug = currentSpan().export();
// Create chat completion with file data
const completion = await client.chat.completions.create({
model: "gpt-4o",
messages: [
{
role: "system",
content: SYSTEM_PROMPT,
},
{
role: "user",
content: [
{
type: "file",
file: {
filename: pdfFile.filename,
file_data: `data:application/pdf;base64,${base64String}`,
},
},
{
type: "text",
text: userPrompt,
},
],
},
],
max_tokens: 500,
});
const summary = completion.choices[0]?.message?.content;
// if no summary is generated, log an error and return
if (!summary) {
console.warn("No summary generated");
return;
}
// Console log that the summary was created
console.log(
`\nEarnings Summary for ${pdfFile.filename}: Summary Created! View in the Braintrust UI!\n`,
);
// log the output of the LLM call to the root span
rootSpan.log({
output: summary,
});
// Log system prompt span
await logSystemPrompt(pdfFile.filename, pdfFile.url, summary, rootSpanSlug);
// Log user prompt span
await logUserPrompt(
pdfFile.filename,
pdfFile.url,
userPrompt,
summary,
rootSpanSlug,
base64String,
);
},
logger,
);