Files
langchain-evolution-deck/final-compile.js
T
petya 75601988c2 Initial commit: LangChain evolution tutorial deck (132 slides)
- Cover, TOC, 5 dividers, 3 recap slides
- 5 sections (chains, langgraph, deepagents, openswe, ecosystem)
- design-system.js with theme tokens + 9 helper functions
- research/: timeline + sources + per-tech notes
- final-compile.js + merge.js for rebuild pipeline
- output/: langchain-evolution.pptx (2.3 MB) + langchain-evolution.pdf (1.1 MB) + 7 sample previews
2026-06-22 11:29:03 +03:00

270 lines
10 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* final-compile.js
* Создаёт:
* - build/intro.pptx (cover + TOC)
* - build/dividers.pptx (5 dividers между секциями)
* - build/recap.pptx (3 recap слайда: timeline, what's next, closing)
* Затем вызывает merge.js для склейки всех в один .pptx.
*/
'use strict';
const path = require('path');
const fs = require('fs');
const ds = require('./design-system');
const { theme, palette, fonts, sizes, layouts, helpers } = ds;
const pptxgen = require('pptxgenjs');
const WORKSPACE = __dirname;
const SLIDES = path.join(WORKSPACE, 'slides');
const BUILD = path.join(WORKSPACE, 'build');
fs.mkdirSync(BUILD, { recursive: true });
const SECTIONS = [
{ dir: 'section1-chains', title: 'LangChain 1.0', subtitle: 'chains, LCEL, agents, retrievers' },
{ dir: 'section2-langgraph', title: 'LangGraph 1.0', subtitle: 'state, nodes, persistence, HITL' },
{ dir: 'section3-deepagents', title: 'Deep Agents', subtitle: 'harness, todos, virtual FS, subagents' },
{ dir: 'section4-openswe', title: 'Open SWE', subtitle: 'async coding agent, triggers, dashboard' },
{ dir: 'section5-ecosystem', title: 'Экосистема', subtitle: 'LangSmith, Studio, deployment' },
];
// -------- INTRO (cover + TOC) --------
function buildIntro(pres) {
// Slide 1 -- cover
const s1 = pres.addSlide();
helpers.slideBase(s1, pres, theme);
// top accent
s1.addShape(pres.ShapeType.rect, { x: 0, y: 0, w: 10, h: 0.15, fill: { color: palette.accent.primary }, line: { type: 'none' } });
helpers.addHeader(s1, pres, theme, {
eyebrow: 'DEEP DIVE / TUTORIAL',
sectionNumber: 0,
title: 'Эволюция LangChain',
});
// subtitle
s1.addText('от chains до Deep Agents и Open SWE', {
x: 0.5, y: 1.85, w: 9, h: 0.5,
fontFace: fonts.ui, fontSize: 24, color: palette.text.secondary, bold: false,
});
// gold bar
s1.addShape(pres.ShapeType.rect, { x: 0.5, y: 2.55, w: 1.5, h: 0.06, fill: { color: palette.accent.secondary }, line: { type: 'none' } });
// description
s1.addText(
'Большой tutorial по экосистеме LangChain: chains, LCEL, LangGraph, Deep Agents, Open SWE. ' +
'Python 1.0+, реальные API, плотный код.',
{
x: 0.5, y: 2.85, w: 9, h: 1.5,
fontFace: fonts.ui, fontSize: 16, color: palette.text.secondary,
}
);
// footer meta
s1.addText('100+ слайдов | 2022 -- 2026 | Python 1.0+', {
x: 0.5, y: 5.15, w: 9, h: 0.3,
fontFace: fonts.ui, fontSize: 11, color: palette.text.muted, align: 'center',
});
helpers.addPageNumber(s1, pres, theme, 1);
// Slide 2 -- TOC
const s2 = pres.addSlide();
helpers.slideBase(s2, pres, theme);
helpers.addHeader(s2, pres, theme, {
eyebrow: 'CONTENTS',
sectionNumber: 0,
title: 'Содержание',
});
let y = layouts.CONTENT_TOP + 0.1;
SECTIONS.forEach((sec, i) => {
// card
s2.addShape(pres.ShapeType.roundRect, {
x: 0.5, y: y, w: 9, h: 0.55,
fill: { color: palette.bg.elevated },
line: { color: palette.border.subtle, width: 0.5 },
rectRadius: 0.08,
});
// number badge
s2.addShape(pres.ShapeType.roundRect, {
x: 0.65, y: y + 0.1, w: 0.35, h: 0.35,
fill: { color: palette.accent.primary },
line: { type: 'none' },
rectRadius: 0.04,
});
s2.addText(String(i + 1), {
x: 0.65, y: y + 0.12, w: 0.35, h: 0.3,
fontFace: fonts.ui, fontSize: 14, color: palette.bg.primary, bold: true, align: 'center',
});
s2.addText(sec.title + ' -- ' + sec.subtitle, {
x: 1.15, y: y + 0.08, w: 7.5, h: 0.4,
fontFace: fonts.ui, fontSize: 14, color: palette.text.primary, bold: true,
});
y += 0.65;
});
// total
s2.addText('Всего: 122 content слайдов + cover, TOC, 5 dividers, recap = 132', {
x: 0.5, y: 5.05, w: 9, h: 0.3,
fontFace: fonts.ui, fontSize: 12, color: palette.accent.secondary, align: 'center',
});
helpers.addPageNumber(s2, pres, theme, 2);
}
// -------- DIVIDERS (5) --------
function buildDividers(pres) {
SECTIONS.forEach((sec, i) => {
const slide = pres.addSlide();
helpers.slideBase(slide, pres, theme);
// big stage number
slide.addShape(pres.ShapeType.rect, {
x: 0, y: 0, w: 10, h: 0.15,
fill: { color: palette.accent.primary }, line: { type: 'none' },
});
// huge number
slide.addText('STAGE ' + (i + 1), {
x: 0.5, y: 1.4, w: 9, h: 0.5,
fontFace: fonts.ui, fontSize: 18, color: palette.accent.primary, bold: true, charSpacing: 6,
});
slide.addText(sec.title, {
x: 0.5, y: 2.0, w: 9, h: 1.2,
fontFace: fonts.ui, fontSize: 60, color: palette.text.primary, bold: true,
});
slide.addText(sec.subtitle, {
x: 0.5, y: 3.2, w: 9, h: 0.5,
fontFace: fonts.ui, fontSize: 22, color: palette.text.secondary,
});
// gold accent line
slide.addShape(pres.ShapeType.rect, {
x: 0.5, y: 3.85, w: 1.5, h: 0.05,
fill: { color: palette.accent.secondary }, line: { type: 'none' },
});
// section nav
slide.addText('Раздел ' + (i + 1) + ' из ' + SECTIONS.length, {
x: 0.5, y: 5.0, w: 9, h: 0.3,
fontFace: fonts.ui, fontSize: 12, color: palette.text.muted, align: 'center',
});
helpers.addPageNumber(slide, pres, theme, 0); // 0 = no number
});
}
// -------- RECAP (3) --------
function buildRecap(pres) {
// Recap 1 -- Timeline
let s = pres.addSlide();
helpers.slideBase(s, pres, theme);
helpers.addHeader(s, pres, theme, {
eyebrow: 'TIMELINE',
sectionNumber: 0,
title: 'Полная карта эволюции',
});
s.addText(
[
{ text: '2022-10 ', options: { color: palette.accent.primary, bold: true } },
{ text: 'LangChain 0.1 -- запуск фреймворка chains\n', options: { color: palette.text.primary } },
{ text: '2023-10 ', options: { color: palette.accent.primary, bold: true } },
{ text: 'LangChain 0.1 (stable) -- первый production-ready\n', options: { color: palette.text.primary } },
{ text: '2024-01 ', options: { color: palette.accent.primary, bold: true } },
{ text: 'LangGraph 0.1 -- stateful графы\n', options: { color: palette.text.primary } },
{ text: '2025-08 ', options: { color: palette.accent.primary, bold: true } },
{ text: 'Deep Agents 0.x -- harness с subagents\n', options: { color: palette.text.primary } },
{ text: '2025-10 ', options: { color: palette.accent.secondary, bold: true } },
{ text: 'LangChain 1.0 + LangGraph 1.0 (22.10.2025)\n', options: { color: palette.text.primary } },
{ text: '2025-12 ', options: { color: palette.accent.secondary, bold: true } },
{ text: 'Open SWE 1.0 -- async coding agent', options: { color: palette.text.primary } },
],
{
x: 0.7, y: 1.5, w: 8.6, h: 3.4,
fontFace: 'JetBrains Mono', fontSize: 13, color: palette.text.primary,
paraSpaceAfter: 8,
}
);
helpers.addPageNumber(s, pres, theme, 130);
// Recap 2 -- What's next
s = pres.addSlide();
helpers.slideBase(s, pres, theme);
helpers.addHeader(s, pres, theme, {
eyebrow: 'WHAT IS NEXT',
sectionNumber: 0,
title: 'Куда движется стек',
});
const items = [
['Subagents', 'делегирование доменных задач с собственным state'],
['Virtual filesystem', 'stateful scratchpad для reasoning-агентов'],
['Human-in-the-loop', 'production-ready approval flows в LangGraph 1.0+'],
['Open SWE', 'async coding agent с GitHub-триггерами и dashboard'],
['LangSmith', 'observability: traces, evals, online monitoring'],
];
let y = 1.5;
items.forEach(([k, v]) => {
s.addText(k, {
x: 0.7, y: y, w: 3, h: 0.4,
fontFace: fonts.ui, fontSize: 16, color: palette.accent.secondary, bold: true,
});
s.addText(v, {
x: 3.8, y: y + 0.05, w: 5.7, h: 0.4,
fontFace: fonts.ui, fontSize: 13, color: palette.text.primary,
});
y += 0.55;
});
helpers.addPageNumber(s, pres, theme, 131);
// Recap 3 -- Closing
s = pres.addSlide();
helpers.slideBase(s, pres, theme);
helpers.addHeader(s, pres, theme, {
eyebrow: 'CLOSING',
sectionNumber: 0,
title: 'Главный тренд',
});
s.addText(
'От chain-of-prompts к stateful агентам с harness и human-in-the-loop.',
{
x: 0.7, y: 1.7, w: 8.6, h: 0.8,
fontFace: fonts.ui, fontSize: 22, color: palette.accent.secondary, bold: true,
}
);
s.addText(
'LangChain 1.0 -- это stable ядро (chains, LCEL, agents, retrievers). ' +
'LangGraph 1.0 -- stateful execution layer. ' +
'Deep Agents -- reasoning harness "из коробки". ' +
'Open SWE -- продуктовая реализация coding agent. ' +
'Всё это работает на Python 1.0+ с @traceable из LangSmith.',
{
x: 0.7, y: 2.7, w: 8.6, h: 1.8,
fontFace: fonts.ui, fontSize: 14, color: palette.text.primary,
}
);
s.addText('Спасибо! | Mavis / 2026 / Python 1.0+', {
x: 0.7, y: 5.0, w: 8.6, h: 0.3,
fontFace: fonts.ui, fontSize: 12, color: palette.text.muted, align: 'center',
});
helpers.addPageNumber(s, pres, theme, 132);
}
// -------- MAIN --------
async function main() {
// intro
let p = new pptxgen();
p.layout = 'LAYOUT_WIDE'; // 13.33x7.5 -- not used since helpers override
p.defineLayout({ name: 'LC_16x9', width: 10, height: 5.625 });
p.layout = 'LC_16x9';
buildIntro(p);
const introPath = path.join(BUILD, 'intro.pptx');
await p.writeFile({ fileName: introPath });
console.log('[final-compile] wrote ' + introPath);
// dividers
p = new pptxgen();
p.defineLayout({ name: 'LC_16x9', width: 10, height: 5.625 });
p.layout = 'LC_16x9';
buildDividers(p);
const divPath = path.join(BUILD, 'dividers.pptx');
await p.writeFile({ fileName: divPath });
console.log('[final-compile] wrote ' + divPath);
// recap
p = new pptxgen();
p.defineLayout({ name: 'LC_16x9', width: 10, height: 5.625 });
p.layout = 'LC_16x9';
buildRecap(p);
const recapPath = path.join(BUILD, 'recap.pptx');
await p.writeFile({ fileName: recapPath });
console.log('[final-compile] wrote ' + recapPath);
}
main().catch((e) => { console.error(e); process.exit(1); });