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
This commit is contained in:
2026-06-22 11:29:03 +03:00
parent ed5b5c91bf
commit 75601988c2
220 changed files with 13069 additions and 3 deletions
+269
View File
@@ -0,0 +1,269 @@
/**
* 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); });