Add 122 Python example scripts + .env.example

Each of the 122 code slides now has a standalone .py script in
examples/slide-NNN/script.py with the LLM provider pattern from
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py:
  - load_dotenv() + ChatOpenAI with base_url=https://llm.brojs.ru/v1
  - OPENAI_API_KEY from .env (with safe (or '' or None) pattern)
  - Same comment block with alternative model/base_url choices

Layout:
  - sec1/sec5: code extracted from slide-NN.js (addCodeBlock)
  - sec2/sec3/sec4: code extracted from sectionN.pptx via python-pptx
    (JetBrains Mono font shapes)

100 scripts contain runnable code, 22 are visual-only (dividers,
intro, recap) and just print the slide title.

Setup:
  cp .env.example .env       # fill OPENAI_API_KEY (or symlink to your
                              # teacher/assistant/.env)
  pip install -r requirements.txt
  python examples/slide-005/script.py
This commit is contained in:
2026-06-22 12:02:47 +03:00
parent 75601988c2
commit 1fd7486a85
125 changed files with 6564 additions and 0 deletions
+55
View File
@@ -0,0 +1,55 @@
# Скопируй этот файл в .env и заполни реальными значениями:
# cp .env.example .env
# # открой .env и заполни OPENAI_API_KEY и другие
#
# Реальный .env НЕ коммитится (см. .gitignore).
# Если у тебя есть рабочий .env в bro-js/agents/teacher/assistant/.env --
# можешь сделать symlink или просто скопировать его сюда.
# ============================================================================
# LLM Provider (используется во всех 122 example-скриптах)
# ============================================================================
# Endpoint by default: https://llm.brojs.ru/v1
# OpenAI-compatible, можно переопределить через OPENAI_BASE_URL
OPENAI_BASE_URL=https://llm.brojs.ru/v1
OPENAI_API_KEY=
# Альтернативные провайдеры (раскомментируй нужный, скрипты автоматически подхватят):
# MINIMAX_API_KEY=sk-cp-...
# GIGACHAT_CREDENTIALS=...
# GIGACHAT_SCOPE=GIGACHAT_API_B2B
# GIGACHAT_MODEL=GigaChat-MAX
# ============================================================================
# Observability (LangSmith) -- опционально, для tracing
# ============================================================================
# LANGSMITH_API_KEY=lsv2_pt_...
# LANGSMITH_ENDPOINT=https://api.smith.langchain.com
# LANGSMITH_TRACING_V2=true
# LANGSMITH_PROJECT=langchain-evolution-deck
# ============================================================================
# Search (Tavily) -- нужен для RAG-слайдов про retrievers
# ============================================================================
# TAVILY_API_KEY=tvly-dev-...
# ============================================================================
# Embeddings (HuggingFace) -- опционально для RAG
# ============================================================================
# HUGGINGFACEHUB_API_KEY=hf_...
# ============================================================================
# Не используется в этой колоде, но есть в teacher/assistant/.env
# ============================================================================
# SMTP_CONFIG='["mail.itpark.tech", 25, false]'
# SMTP_MAIL_LOGIN=academydevops@itpark.tech
# SMTP_MAIL_PASSWORD=...
# MAIL_TO_1=primakovpro@gmail.com
# GITHUB_TOKEN=ghp_...
# GITEA_TOKEN=...
# JOURNAL_MCP_PAT=jrnl_...
+4
View File
@@ -12,3 +12,7 @@ node_modules/
# Python
__pycache__/
*.pyc
.env
# Parser script and intermediate
parse_slides.py
+39
View File
@@ -0,0 +1,39 @@
"""
Slide 1: Untitled
Section 1: LangChain 1.0
Source: slides/section1-chains/slide-01.js
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-001/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# (No extractable code on this slide — visual-only or section divider)
print('Slide 1: Untitled')
+39
View File
@@ -0,0 +1,39 @@
"""
Slide 2: Что такое LangChain в 2025+
Section 1: LangChain 1.0
Source: slides/section1-chains/slide-02.js
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-002/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# (No extractable code on this slide — visual-only or section divider)
print('Slide 2: Что такое LangChain в 2025+')
+49
View File
@@ -0,0 +1,49 @@
"""
Slide 3: pip install -- и сразу в дело
Section 1: LangChain 1.0
Source: slides/section1-chains/slide-03.js
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-003/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 3 ===
# 1. Core -- обязательно для всех остальных пакетов
pip install langchain
# 2. Provider-интеграции -- ставим только те, что нужны
pip install langchain-openai
pip install langchain-anthropic
pip install langchain-google
# 3. (опционально) дополнительные интеграции
pip install langchain-community # ~700 community-пакетов
pip install langchain-classic # legacy chains/AgentExecutor
+49
View File
@@ -0,0 +1,49 @@
"""
Slide 4: Первый вызов модели
Section 1: LangChain 1.0
Source: slides/section1-chains/slide-04.js
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-004/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 4 ===
# Один универсальный инициализатор для всех провайдеров
from langchain.chat_models import init_chat_model
# Формат: "<provider>:<model>"
model = init_chat_model("openai:gpt-4.1-mini")
# invoke -> BaseMessage; нам нужен .content
result = model.invoke("Say hello in one sentence")
print(result.content)
# >>> "Hello! How can I help you today?"
+52
View File
@@ -0,0 +1,52 @@
"""
Slide 5: Переключение провайдера -- одна строка
Section 1: LangChain 1.0
Source: slides/section1-chains/slide-05.js
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-005/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 5 ===
from langchain.chat_models import init_chat_model
# OpenAI
m_openai = init_chat_model("openai:gpt-4.1-mini")
# Anthropic
m_anthropic = init_chat_model("anthropic:claude-3-7-sonnet-latest")
# Google Vertex AI
m_google = init_chat_model("google_vertexai:gemini-2.0-flash")
# Все три -- объекты BaseChatModel. Один и тот же .invoke()
for m in [m_openai, m_anthropic, m_google]:
print(type(m).__name__, ":", m.invoke("ping").content[:30])
+54
View File
@@ -0,0 +1,54 @@
"""
Slide 6: Стандартизированные сообщения
Section 1: LangChain 1.0
Source: slides/section1-chains/slide-06.js
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-006/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 6 ===
from langchain.messages import (
HumanMessage, AIMessage, SystemMessage, ToolMessage,
)
from langchain.chat_models import init_chat_model
model = init_chat_model("openai:gpt-4.1-mini")
messages = [
SystemMessage(content="You are a concise assistant."),
HumanMessage(content="What is LCEL?"),
AIMessage(content="LCEL = pipe-based composition in LangChain."),
HumanMessage(content="Show a one-line example."),
]
response = model.invoke(messages)
print(response.content)
+55
View File
@@ -0,0 +1,55 @@
"""
Slide 7: Потоковый вывод -- token за токеном
Section 1: LangChain 1.0
Source: slides/section1-chains/slide-07.js
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-007/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 7 ===
from langchain.chat_models import init_chat_model
model = init_chat_model("openai:gpt-4.1-mini")
# .stream() -> итератор по AIMessageChunk
for chunk in model.stream("Write a haiku about Python"):
# У каждого chunk-а есть .content (текст) и .response_metadata
print(chunk.content, end="", flush=True)
print() # перевод строки после потока
# Async-вариант: model.astream() -- то же самое в async-контексте
import asyncio
async def main():
async for chunk in model.astream("Write a haiku about async"):
print(chunk.content, end="", flush=True)
+53
View File
@@ -0,0 +1,53 @@
"""
Slide 8: ChatPromptTemplate -- декларативно
Section 1: LangChain 1.0
Source: slides/section1-chains/slide-08.js
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-008/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 8 ===
from langchain_core.prompts import ChatPromptTemplate
from langchain.chat_models import init_chat_model
prompt = ChatPromptTemplate.from_messages([
("system", "Translate the following text to {language}."),
("human", "{text}"),
])
model = init_chat_model("openai:gpt-4.1-mini")
# .invoke() принимает dict и подставляет переменные
messages = prompt.invoke({"language": "French", "text": "Hello world"})
print(messages.to_messages())
# -> [SystemMessage(...), HumanMessage(...)] -- готов к model.invoke()
+62
View File
@@ -0,0 +1,62 @@
"""
Slide 9: MessagesPlaceholder + few-shot
Section 1: LangChain 1.0
Source: slides/section1-chains/slide-09.js
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-009/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 9 ===
from langchain_core.prompts import (
ChatPromptTemplate, MessagesPlaceholder, FewShotChatMessagePromptTemplate,
)
# Few-shot блок: примеры "вопрос -> ответ"
examples = [
{"input": "2+2", "output": "4"},
{"input": "3*3", "output": "9"},
]
example_prompt = ChatPromptTemplate.from_messages([
("human", "{input}"),
("ai", "{output}"),
])
few_shot = FewShotChatMessagePromptTemplate(
example_prompt=example_prompt, examples=examples,
)
# Сборка: system + few-shot + история + текущий вопрос
prompt = ChatPromptTemplate.from_messages([
("system", "You are a math assistant."),
few_shot,
MessagesPlaceholder("history"),
("human", "{question}"),
])
+55
View File
@@ -0,0 +1,55 @@
"""
Slide 10: StrOutputParser -- самый частый
Section 1: LangChain 1.0
Source: slides/section1-chains/slide-10.js
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-010/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 10 ===
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain.chat_models import init_chat_model
prompt = ChatPromptTemplate.from_messages([
("system", "Translate to French."),
("human", "{text}"),
])
model = init_chat_model("openai:gpt-4.1-mini")
# Склеиваем через LCEL: prompt | model | parser
chain = prompt | model | StrOutputParser()
# Теперь на выходе str, а не AIMessage
result = chain.invoke({"text": "Hello world"})
print(type(result).__name__, "->", result)
# >>> str -> "Bonjour le monde"
+58
View File
@@ -0,0 +1,58 @@
"""
Slide 11: PydanticOutputParser -- типизированный выход
Section 1: LangChain 1.0
Source: slides/section1-chains/slide-11.js
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-011/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 11 ===
from pydantic import BaseModel, Field
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import PydanticOutputParser
from langchain.chat_models import init_chat_model
class MovieReview(BaseModel):
title: str = Field(description="Movie title")
rating: int = Field(description="Rating from 1 to 10")
summary: str = Field(description="One-sentence summary")
parser = PydanticOutputParser(pydantic_object=MovieReview)
prompt = ChatPromptTemplate.from_messages([
("system", "Extract review fields.\n{format_instructions}"),
("human", "{review_text}"),
]).partial(format_instructions=parser.get_format_instructions())
chain = prompt | init_chat_model("openai:gpt-4.1-mini") | parser
review = chain.invoke({"review_text": "Inception was brilliant. 9/10."})
print(review.title, review.rating, review.summary)
+55
View File
@@ -0,0 +1,55 @@
"""
Slide 12: with_structured_output -- рекомендованный путь
Section 1: LangChain 1.0
Source: slides/section1-chains/slide-12.js
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-012/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 12 ===
from pydantic import BaseModel, Field
from langchain.chat_models import init_chat_model
class Weather(BaseModel):
city: str = Field(description="City name")
temperature_c: float = Field(description="Temperature in Celsius")
conditions: str = Field(description="Weather summary")
# Один вызов -- и модель возвращает типизированный Pydantic-объект
model = init_chat_model("openai:gpt-4.1-mini")
structured = model.with_structured_output(Weather)
result: Weather = structured.invoke("Weather in Paris?")
print(result.city, result.temperature_c, result.conditions)
# method="json_mode" -- если провайдер не поддерживает tool calling
# structured_json = model.with_structured_output(Weather, method="json_mode")
+57
View File
@@ -0,0 +1,57 @@
"""
Slide 13: | -- декларативная композиция
Section 1: LangChain 1.0
Source: slides/section1-chains/slide-13.js
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-013/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 13 ===
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain.chat_models import init_chat_model
prompt = ChatPromptTemplate.from_messages([
("system", "You are a {style} assistant."),
("human", "{question}"),
])
model = init_chat_model("openai:gpt-4.1-mini")
# prompt, model, parser -- все три реализуют Runnable
# Оператор | склеивает их в один chain
chain = prompt | model | StrOutputParser()
# type(chain) -> RunnableSequence
print(type(chain).__name__)
# invoke -> dict на вход, str на выход
print(chain.invoke({"style": "concise", "question": "What is LCEL?"}))
+54
View File
@@ -0,0 +1,54 @@
"""
Slide 14: invoke / batch / stream -- без смены кода
Section 1: LangChain 1.0
Source: slides/section1-chains/slide-14.js
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-014/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 14 ===
chain = prompt | model | StrOutputParser()
# 1. invoke -- один вход, один выход
out_one = chain.invoke({"language": "French", "text": "Good morning"})
# 2. batch -- список входов, список выходов (параллельно)
out_many = chain.batch([
{"language": "French", "text": "Good morning"},
{"language": "German", "text": "Good morning"},
{"language": "Spanish", "text": "Good morning"},
])
print(out_many) # ["Bonjour", "Guten Morgen", "Buenos dias"]
# 3. stream -- итератор по чанкам (стримит последний Runnable)
for chunk in chain.stream({"language": "French", "text": "Stream me"}):
print(chunk, end="", flush=True)
+59
View File
@@ -0,0 +1,59 @@
"""
Slide 15: async + config -- полный контроль
Section 1: LangChain 1.0
Source: slides/section1-chains/slide-15.js
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-015/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 15 ===
import asyncio
from langchain_core.runnables import ConfigurableField
# Любой Runnable имеет ainvoke / astream / abatch
async def main():
# Один async-вызов
result = await chain.ainvoke({"language": "French", "text": "Hi"})
# Async stream
async for chunk in chain.astream({"language": "French", "text": "Hi"}):
print(chunk, end="", flush=True)
asyncio.run(main())
# configurable_fields -- параметры, которые можно переопределять
# на лету через config={"configurable": {...}}
configurable_chain = init_chat_model("openai:gpt-4.1-mini",
temperature=0.7).configurable_fields(
temperature=ConfigurableField(id="temperature"),
)
# configurable_chain.invoke(messages, config={"configurable": {"temperature": 0.0}})
+57
View File
@@ -0,0 +1,57 @@
"""
Slide 16: RunnableLambda + RunnablePassthrough
Section 1: LangChain 1.0
Source: slides/section1-chains/slide-16.js
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-016/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 16 ===
from langchain_core.runnables import RunnableLambda, RunnablePassthrough
# RunnableLambda -- оборачивает произвольную функцию
upper = RunnableLambda(lambda x: x.upper())
word_count = RunnableLambda(lambda text: {"text": text, "words": len(text.split())})
# RunnablePassthrough -- пропускает вход дальше (для branching)
passthrough = RunnablePassthrough()
# Пример: текст -> uppercase -> посчитать слова -> смёрджить с оригиналом
chain = (
word_count
| RunnablePassthrough.assign(upper=upper)
)
result = chain.invoke("hello world from langchain")
print(result)
# {"text": "hello world from langchain",
# "words": 4, "upper": "HELLO WORLD FROM LANGCHAIN"}
+55
View File
@@ -0,0 +1,55 @@
"""
Slide 17: Parallel + Branch -- fan-out и роутинг
Section 1: LangChain 1.0
Source: slides/section1-chains/slide-17.js
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-017/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 17 ===
from langchain_core.runnables import RunnableParallel, RunnableBranch
# Parallel -- один вход, несколько параллельных Runnable-ов, dict на выходе
joke_chain = ChatPromptTemplate.from_template("Tell a joke about {topic}") | model
poem_chain = ChatPromptTemplate.from_template("Write a poem about {topic}") | model
parallel = RunnableParallel(joke=joke_chain, poem=poem_chain)
result = parallel.invoke({"topic": "cats"})
print(result.keys()) # dict_keys(["joke", "poem"])
# Branch -- if/else роутинг по условию
branch = RunnableBranch(
(lambda x: "code" in x["topic"].lower(), code_chain),
(lambda x: "math" in x["topic"].lower(), math_chain),
general_chain, # default
)
print(branch.invoke({"topic": "code review"}))
+63
View File
@@ -0,0 +1,63 @@
"""
Slide 18: Vector store -> retriever -> RAG-цепочка
Section 1: LangChain 1.0
Source: slides/section1-chains/slide-18.js
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-018/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 18 ===
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import FAISS
from langchain_core.runnables import RunnablePassthrough
# 1. Эмбеддинги и индекс
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
docs = ["Cats are mammals.", "Python is a programming language.",
"LangChain helps build LLM apps."]
vectorstore = FAISS.from_texts(docs, embedding=embeddings)
# 2. .as_retriever() превращает store в Runnable
retriever = vectorstore.as_retriever(search_kwargs={"k": 2})
# 3. RAG-цепочка через LCEL: context + question -> answer
from langchain_core.prompts import ChatPromptTemplate
from langchain.chat_models import init_chat_model
prompt = ChatPromptTemplate.from_template(
"Answer based on context.\nContext: {context}\nQ: {question}"
)
model = init_chat_model("openai:gpt-4.1-mini")
rag = (
{"context": retriever, "question": RunnablePassthrough()}
| prompt | model | StrOutputParser()
)
+58
View File
@@ -0,0 +1,58 @@
"""
Slide 19: @tool -- любая функция становится инструментом
Section 1: LangChain 1.0
Source: slides/section1-chains/slide-19.js
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-019/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 19 ===
from langchain.tools import tool
from langchain.chat_models import init_chat_model
@tool
def get_weather(city: str) -> str:
"""Get the current weather for a given city."""
return f"Sunny, 22C in {city}"
@tool
def search_docs(query: str, top_k: int = 3) -> list[str]:
"""Search internal documentation. Returns top_k snippets."""
return [f"doc about {query} #{i}" for i in range(top_k)]
# bind_tools -- модель знает, какие функции можно вызвать
model = init_chat_model("openai:gpt-4.1-mini")
bound = model.bind_tools([get_weather, search_docs])
result = bound.invoke("What is the weather in Paris?")
print(result.tool_calls)
# [{"name": "get_weather", "args": {"city": "Paris"}, "id": "..."}]
+57
View File
@@ -0,0 +1,57 @@
"""
Slide 20: create_agent -- один вход для всех агентов
Section 1: LangChain 1.0
Source: slides/section1-chains/slide-20.js
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-020/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 20 ===
from langchain.agents import create_agent
from langchain.tools import tool
@tool
def get_weather(city: str) -> str:
"""Get weather for a city."""
return f"Sunny, 22C in {city}"
# Один вызов вместо create_react_agent / create_openai_functions_agent / ...
agent = create_agent(
model="openai:gpt-4.1",
tools=[get_weather],
system_prompt="You are a weather assistant.",
)
# invoke -> dict {"messages": [...]}; последнее сообщение = ответ
result = agent.invoke({"messages": [{"role": "user",
"content": "weather in Paris?"}]})
print(result["messages"][-1].content)
+59
View File
@@ -0,0 +1,59 @@
"""
Slide 21: Краткосрочная память: thread + checkpointer
Section 1: LangChain 1.0
Source: slides/section1-chains/slide-21.js
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-021/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 21 ===
from langchain.agents import create_agent
from langgraph.checkpoint.memory import InMemorySaver
checkpointer = InMemorySaver()
agent = create_agent(
model="openai:gpt-4.1-mini",
tools=[...],
checkpointer=checkpointer, # <-- persistent state
)
config = {"configurable": {"thread_id": "user-42"}}
# Первый turn
agent.invoke({"messages": [{"role": "user",
"content": "My name is Alice."}]}, config=config)
# Второй turn -- модель помнит имя
result = agent.invoke({"messages": [{"role": "user",
"content": "What is my name?"}]}, config=config)
print(result["messages"][-1].content) # "Alice"
+59
View File
@@ -0,0 +1,59 @@
"""
Slide 22: Долгосрочная память: store + namespace
Section 1: LangChain 1.0
Source: slides/section1-chains/slide-22.js
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-022/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 22 ===
from langgraph.store.memory import InMemoryStore
from langchain.agents import create_agent
from langchain.embeddings import init_embeddings
# Store может быть in-memory (dev) или Postgres (prod)
store = InMemoryStore(
index={"embed": init_embeddings("openai:text-embedding-3-small"),
"dims": 1536},
)
agent = create_agent(
model="openai:gpt-4.1-mini",
tools=[...],
store=store,
)
# Namespace = ("user-id", "facts") -- разделение по пользователям
ns = ("user-42", "facts")
store.put(ns, "pref-1", {"text": "User prefers concise answers."})
# В новой сессии store.search(ns, query="preferences") вернёт факты
+60
View File
@@ -0,0 +1,60 @@
"""
Slide 23: Cross-cutting concerns одной строкой
Section 1: LangChain 1.0
Source: slides/section1-chains/slide-23.js
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-023/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 23 ===
from langchain.agents import create_agent
from langchain.agents.middleware import (
HumanInTheLoopMiddleware,
PIIRedactionMiddleware,
SummarizationMiddleware,
)
from langchain.tools import tool
@tool
def send_email(to: str, body: str) -> str:
"""Send an email to recipient."""
return f"sent to {to}"
agent = create_agent(
model="openai:gpt-4.1",
tools=[send_email],
middleware=[
HumanInTheLoopMiddleware(interrupt_on={"send_email": True}),
PIIRedactionMiddleware(redact_emails=True, redact_phones=True),
SummarizationMiddleware(trigger=("tokens", 4000)),
],
)
+39
View File
@@ -0,0 +1,39 @@
"""
Slide 24: Что нового в 1.0 vs 0.3
Section 1: LangChain 1.0
Source: slides/section1-chains/slide-24.js
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-024/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# (No extractable code on this slide — visual-only or section divider)
print('Slide 24: Что нового в 1.0 vs 0.3')
+54
View File
@@ -0,0 +1,54 @@
"""
Slide 25: JS-аналог: что есть, чего нет
Section 1: LangChain 1.0
Source: slides/section1-chains/slide-25.js
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-025/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 25 ===
import { initChatModel } from "langchain/chat_models/universal";
import { createAgent } from "langchain/agents";
import { tool } from "@langchain/core/tools";
import { z } from "zod";
const getWeather = tool(
async ({ city }) => `Sunny, 22C in ${city}`,
{ name: "get_weather", description: "Get weather",
schema: z.object({ city: z.string() }) },
);
const model = await initChatModel("openai:gpt-4.1");
const agent = createAgent({ model, tools: [getWeather] });
const result = await agent.invoke({
messages: [{ role: "user", content: "weather in Paris?" }],
});
+39
View File
@@ -0,0 +1,39 @@
"""
Slide 26: Когда LangChain 1.0 -- правильный выбор
Section 1: LangChain 1.0
Source: slides/section1-chains/slide-26.js
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-026/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# (No extractable code on this slide — visual-only or section divider)
print('Slide 26: Когда LangChain 1.0 -- правильный выбор')
+39
View File
@@ -0,0 +1,39 @@
"""
Slide 27: Дальше: LangGraph -- явный control flow
Section 1: LangChain 1.0
Source: slides/section1-chains/slide-27.js
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-027/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# (No extractable code on this slide — visual-only or section divider)
print('Slide 27: Дальше: LangGraph -- явный control flow')
+39
View File
@@ -0,0 +1,39 @@
"""
Slide 28: LangGraph 1.0: stateful runtime
Section 2: LangGraph 1.0
Source: slides/section2-langgraph/section2.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-028/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# (No extractable code on this slide — visual-only or section divider)
print('Slide 28: LangGraph 1.0: stateful runtime')
+39
View File
@@ -0,0 +1,39 @@
"""
Slide 29: Slide 2
Section 2: LangGraph 1.0
Source: slides/section2-langgraph/section2.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-029/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# (No extractable code on this slide — visual-only or section divider)
print('Slide 29: Slide 2')
+46
View File
@@ -0,0 +1,46 @@
"""
Slide 30: Slide 3
Section 2: LangGraph 1.0
Source: slides/section2-langgraph/section2.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-030/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 30 ===
pip install -U langgraph
# extras: postgres / sqlite checkpointers -- отдельные пакеты
pip install -U langgraph langgraph-checkpoint-postgres
pip install -U langgraph langgraph-checkpoint-sqlite
# JS / TypeScript
npm install @langchain/langgraph @langchain/langgraph-checkpoint
+59
View File
@@ -0,0 +1,59 @@
"""
Slide 31: Slide 4
Section 2: LangGraph 1.0
Source: slides/section2-langgraph/section2.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-031/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 31 ===
from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START, END
> class State(TypedDict):
> question: str
> answer: str
steps: int
def answer(state: State) -> dict:
return {"answer": f"echo: {state['question']}", "steps": 1}
builder = StateGraph(State)
builder.add_node("answer", answer)
builder.add_edge(START, "answer")
builder.add_edge("answer", END)
graph = builder.compile()
>
> print(graph.invoke({"question": "hi", "steps": 0}))
> # -> {'question': 'hi', 'answer': 'echo: hi', 'steps': 1}
// note: snippet has 19 lines, card fits ~17
+60
View File
@@ -0,0 +1,60 @@
"""
Slide 32: Slide 5
Section 2: LangGraph 1.0
Source: slides/section2-langgraph/section2.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-032/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 32 ===
from typing import Annotated
from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import add_messages
class State(TypedDict):
# reducer add_messages склеивает списки сообщений по правилам
> messages: Annotated[list, add_messages]
def echo(state: State):
last = state["messages"][-1]
> return {"messages": [{"role": "assistant", "content": f"echo: {last.content}"}]}
>
g = StateGraph(State)
g.add_node("echo", echo)
g.add_edge(START, "echo")
g.add_edge("echo", END)
app = g.compile()
print(app.invoke({"messages": [{"role": "user", "content": "hi"}]}))
// note: snippet has 20 lines, card fits ~18
+65
View File
@@ -0,0 +1,65 @@
"""
Slide 33: Slide 6
Section 2: LangGraph 1.0
Source: slides/section2-langgraph/section2.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-033/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 33 ===
import operator
from typing import Annotated
from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START, END
class State(TypedDict):
# каждый узел возвращает кусок списка, operator.add склеивает
log: Annotated[list[str], operator.add]
> tokens: Annotated[int, operator.add]
>
def step(state: State):
return {"log": ["step-1"], "tokens": 12}
def another(state: State):
return {"log": ["step-2"], "tokens": 7}
g = StateGraph(State)
g.add_node("a", step)
g.add_node("b", another)
g.add_edge(START, "a")
g.add_edge("a", "b")
g.add_edge("b", END)
app = g.compile()
print(app.invoke({"log": [], "tokens": 0}))
# -> {'log': ['step-1', 'step-2'], 'tokens': 19}
// note: snippet has 25 lines, card fits ~18
+61
View File
@@ -0,0 +1,61 @@
"""
Slide 34: Slide 7
Section 2: LangGraph 1.0
Source: slides/section2-langgraph/section2.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-034/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 34 ===
from dataclasses import dataclass, field
from typing import Annotated
from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import add_messages
@dataclass
class State:
question: str = ""
> # dataclass + Annotated -- каналы работают точно так же
> messages: Annotated[list, add_messages] = field(default_factory=list)
approved: bool = False
def greet(state: State):
return {"messages": [{"role": "assistant", "content": f"hi, {state.question}"}]}
g = StateGraph(State)
g.add_node("greet", greet)
g.add_edge(START, "greet")
g.add_edge("greet", END)
app = g.compile()
print(app.invoke(State(question="alex")))
// note: snippet has 21 lines, card fits ~18
+55
View File
@@ -0,0 +1,55 @@
"""
Slide 35: Slide 8
Section 2: LangGraph 1.0
Source: slides/section2-langgraph/section2.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-035/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 35 ===
from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START, END
class State(TypedDict):
n: int
def inc(state: State):
return {"n": state["n"] + 1}
builder = StateGraph(State)
builder.add_node("inc", inc) # регистрируем узел
> builder.add_edge(START, "inc") # поток входа
> builder.add_edge("inc", END) # поток выхода
>
graph = builder.compile() # компиляция -- граф готов к invoke
> print(graph.invoke({"n": 0})) # -> {'n': 1}
+61
View File
@@ -0,0 +1,61 @@
"""
Slide 36: Slide 9
Section 2: LangGraph 1.0
Source: slides/section2-langgraph/section2.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-036/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 36 ===
# START и END -- это специальные sentinel-узлы, не callable
from langgraph.graph import StateGraph, START, END
>
class State(TypedDict):
text: str
def upper(state: State):
return {"text": state["text"].upper()}
def exclaim(state: State):
return {"text": state["text"] + "!"}
g = StateGraph(State)
> g.add_node("upper", upper)
g.add_node("exclaim", exclaim)
> g.add_edge(START, "upper") # вход в граф
> g.add_edge("upper", "exclaim") # внутреннее ребро
g.add_edge("exclaim", END) # выход из графа
app = g.compile()
print(app.invoke({"text": "hi"})) # -> {'text': 'HI!'}
// note: snippet has 21 lines, card fits ~18
+64
View File
@@ -0,0 +1,64 @@
"""
Slide 37: Slide 10
Section 2: LangGraph 1.0
Source: slides/section2-langgraph/section2.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-037/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 37 ===
import asyncio
from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START, END
class State(TypedDict):
out: str
def sync_node(state: State): # обычная функция
return {"out": "sync-ok"}
> async def async_node(state: State): # async тоже работает
await asyncio.sleep(0)
> return {"out": "async-ok"}
g = StateGraph(State)
g.add_node("s", sync_node)
g.add_node("a", async_node)
g.add_edge(START, "s")
g.add_edge("s", "a")
g.add_edge("a", END)
app = g.compile()
print(app.invoke({"out": ""}))
print(asyncio.run(app.ainvoke({"out": ""})))
// note: snippet has 24 lines, card fits ~18
+60
View File
@@ -0,0 +1,60 @@
"""
Slide 38: Slide 11
Section 2: LangGraph 1.0
Source: slides/section2-langgraph/section2.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-038/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 38 ===
from langgraph.graph import StateGraph, START, END
from langgraph.types import Command
from typing_extensions import TypedDict
from typing import Literal
class State(TypedDict):
n: int
> def decide(state: State) -> Command[Literal["inc", "halt"]]:
> # Command(update, goto) -- обновляет state и сам выбирает узел
if state["n"] < 3:
> return Command(update={"n": state["n"] + 1}, goto="inc")
return Command(update={}, goto="halt")
g = StateGraph(State)
g.add_node("decide", decide)
g.add_node("inc", inc)
g.add_node("halt", lambda s: s)
g.add_edge(START, "decide")
g.add_edge("inc", "decide")
g.add_edge("halt", END)
app = g.compile()
print(app.invoke({"n": 0}))
// note: snippet has 20 lines, card fits ~18
+68
View File
@@ -0,0 +1,68 @@
"""
Slide 39: Slide 12
Section 2: LangGraph 1.0
Source: slides/section2-langgraph/section2.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-039/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 39 ===
from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START, END
class State(TypedDict):
needs_tool: bool
answer: str
def agent(state: State) -> dict:
return {"answer": "model-output"}
def tool_node(state: State) -> dict:
return {"answer": "tool-output"}
def route(state: State) -> str:
# возвращаем ключ, который есть в path_map ниже
return "tool_node" if state["needs_tool"] else END
g = StateGraph(State)
> g.add_node("agent", agent)
> g.add_node("tool_node", tool_node)
> g.add_edge(START, "agent")
> g.add_conditional_edges("agent", route, {
> "tool_node": "tool_node",
END: END,
})
g.add_edge("tool_node", END)
app = g.compile()
print(app.invoke({"needs_tool": True, "answer": ""}))
// note: snippet has 28 lines, card fits ~18
+61
View File
@@ -0,0 +1,61 @@
"""
Slide 40: Slide 13
Section 2: LangGraph 1.0
Source: slides/section2-langgraph/section2.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-040/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 40 ===
# агентный цикл: agent <-> tools, выход когда done=true
from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START, END
class State(TypedDict):
done: bool
iter: int
def agent(state: State) -> dict:
return {"iter": state["iter"] + 1, "done": state["iter"] >= 3}
def maybe_continue(state: State) -> str:
return "agent" if not state["done"] else END
> g = StateGraph(State)
> g.add_node("agent", agent)
g.add_edge(START, "agent")
g.add_conditional_edges("agent", maybe_continue, {"agent": "agent", END: END})
app = g.compile()
print(app.invoke({"done": False, "iter": 0}))
# agent крутится 3 раза, потом уходит в END
// note: snippet has 21 lines, card fits ~18
+66
View File
@@ -0,0 +1,66 @@
"""
Slide 41: Slide 14
Section 2: LangGraph 1.0
Source: slides/section2-langgraph/section2.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-041/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 41 ===
from typing import Annotated
from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import add_messages
from langgraph.checkpoint.memory import InMemorySaver
class State(TypedDict):
messages: Annotated[list, add_messages]
def echo(state: State):
last = state["messages"][-1]
return {"messages": [{"role": "assistant", "content": f"echo: {last.content}"}]}
g = StateGraph(State)
g.add_node("echo", echo)
g.add_edge(START, "echo")
g.add_edge("echo", END)
# checkpointer -- обязателен для thread persistence
checkpointer = InMemorySaver()
app = g.compile(checkpointer=checkpointer)
>
> cfg = {"configurable": {"thread_id": "user-1"}}
app.invoke({"messages": [{"role": "user", "content": "hi"}]}, cfg)
> app.invoke({"messages": [{"role": "user", "content": "again"}]}, cfg)
> # второй вызов видит все сообщения первого: thread persistence работает
// note: snippet has 26 lines, card fits ~18
+59
View File
@@ -0,0 +1,59 @@
"""
Slide 42: Slide 15
Section 2: LangGraph 1.0
Source: slides/section2-langgraph/section2.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-042/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 42 ===
> # SQLite -- файл на диске, идеален для dev / small-prod
from langgraph.checkpoint.sqlite import SqliteSaver
>
> with SqliteSaver.from_conn_string("./checkpoints.db") as cp:
> app = g.compile(checkpointer=cp)
cfg = {"configurable": {"thread_id": "u1"}}
app.invoke({"messages": []}, cfg)
# данные переживают рестарт процесса.
# Для asyncio-варианта -- aiosqlite.
> # Postgres -- production-grade, multi-instance
from langgraph.checkpoint.postgres import PostgresSaver
>
DB = "postgresql://user:pass@host:5432/lg"
with PostgresSaver.from_conn_string(DB) as cp:
> # первый запуск создаст schema
cp.setup()
app = g.compile(checkpointer=cp)
cfg = {"configurable": {"thread_id": "u1"}}
app.invoke({"messages": []}, cfg)
+50
View File
@@ -0,0 +1,50 @@
"""
Slide 43: Slide 16
Section 2: LangGraph 1.0
Source: slides/section2-langgraph/section2.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-043/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 43 ===
# После invoke можно достать текущий snapshot:
> snapshot = app.get_state(cfg)
# snapshot -- это StateSnapshot с полями:
> # .config -- thread_id + checkpoint_id
> # .metadata -- step, source, writes
> # .values -- текущие значения всех каналов state
> # .next -- tuple узлов, которые будут выполняться следующими
> # .tasks -- PregelTask с pending/result/error
print(snapshot.next) # () -- граф завершён
print(snapshot.values["messages"][-1].content)
+50
View File
@@ -0,0 +1,50 @@
"""
Slide 44: Slide 17
Section 2: LangGraph 1.0
Source: slides/section2-langgraph/section2.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-044/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 44 ===
# Каждый super-step -- отдельный checkpoint в thread
> history = list(app.get_state_history(cfg))
>
> # history[0] -- последний шаг (самый свежий)
# history[-1] -- самый первый (начало сессии)
> for i, snap in enumerate(history):
print(i, snap.metadata.get("step"), snap.values.get("iter"))
> # replays = форк от любого прошлого snapshot:
> old = history[2].config
app.invoke(None, old) # переигрывает только следующие шаги
+50
View File
@@ -0,0 +1,50 @@
"""
Slide 45: Slide 18
Section 2: LangGraph 1.0
Source: slides/section2-langgraph/section2.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-045/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 45 ===
# patch значения канала прямо в snapshot -- создаётся новый checkpoint
> app.update_state(
> cfg,
> values={"messages": [{"role": "user", "content": "rewind"}]},
> as_node="user_input", # от имени какого узла пишем
)
# Дальше invoke(None, cfg) переигрывает граф с нового состояния
app.invoke(None, cfg)
>
> # Типичный приём: "что если пользователь сказал не X, а Y?" --
# ответвляемся, смотрим альтернативный прогон без потери истории.
+60
View File
@@ -0,0 +1,60 @@
"""
Slide 46: Slide 19
Section 2: LangGraph 1.0
Source: slides/section2-langgraph/section2.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-046/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 46 ===
from langgraph.types import interrupt, Command
from langgraph.graph import StateGraph, START, END
from langgraph.checkpoint.memory import InMemorySaver
from typing_extensions import TypedDict
class State(TypedDict):
question: str
approved: bool
def ask(state: State):
# interrupt() -- пауза. Возвращает значение из Command(resume=...)
> answer = interrupt({"question": "Approve sending this message?"})
return {"approved": answer == "yes"}
g = StateGraph(State)
g.add_node("ask", ask)
g.add_edge(START, "ask")
g.add_edge("ask", END)
app = g.compile(checkpointer=InMemorySaver())
> cfg = {"configurable": {"thread_id": "approval-1"}}
> app.invoke({"question": "send email", "approved": False}, cfg) # пауза
> result = app.invoke(Command(resume="yes"), cfg) # resume
print(result["approved"]) # -> True
// note: snippet has 20 lines, card fits ~18
+39
View File
@@ -0,0 +1,39 @@
"""
Slide 47: Slide 20
Section 2: LangGraph 1.0
Source: slides/section2-langgraph/section2.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-047/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# (No extractable code on this slide — visual-only or section divider)
print('Slide 47: Slide 20')
+56
View File
@@ -0,0 +1,56 @@
"""
Slide 48: Slide 21
Section 2: LangGraph 1.0
Source: slides/section2-langgraph/section2.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-048/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 48 ===
# Узел review -- маршрутизация по ответу человека
from langgraph.types import interrupt, Command
from typing_extensions import TypedDict
class State(TypedDict):
plan: str
executed: bool
def plan(state: State):
return {"plan": "step-A; step-B; step-C"}
> def review(state: State) -> Command:
> # interrupt() возвращает ответ из Command(resume=...)
> decision = interrupt({"plan": state["plan"]})
> if decision == "approve":
> return Command(goto="execute")
> if decision == "abort":
> return Command(goto=END)
return Command(goto="plan") # перепланировать
def execute(state: State):
return {"executed": True}
+55
View File
@@ -0,0 +1,55 @@
"""
Slide 49: Slide 22
Section 2: LangGraph 1.0
Source: slides/section2-langgraph/section2.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-049/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 49 ===
from langgraph.graph import StateGraph, START, END
from langgraph.checkpoint.memory import InMemorySaver
# plan, review, execute -- из предыдущего слайда
g = StateGraph(State)
> g.add_node("plan", plan)
> g.add_node("review", review)
g.add_node("execute", execute)
> g.add_edge(START, "plan")
g.add_edge("plan", "review")
g.add_edge("execute", END)
app = g.compile(checkpointer=InMemorySaver())
# Цикл: каждый review -- это пауза; Command(goto=...) -- ответвление
> # plan -> review -> (approve: execute | abort: END | else: plan)
> cfg = {"configurable": {"thread_id": "u1"}}
app.invoke({"plan": "", "executed": False}, cfg) # пауза 1
app.invoke(Command(resume="approve"), cfg) # resume -> execute
+66
View File
@@ -0,0 +1,66 @@
"""
Slide 50: Slide 23
Section 2: LangGraph 1.0
Source: slides/section2-langgraph/section2.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-050/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 50 ===
from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START, END
class SubState(TypedDict):
internal: str
def inner(state: SubState):
return {"internal": "sub-output"}
# Собираем subgraph -- у него свой state
> sub = StateGraph(SubState)
> sub.add_node("inner", inner)
> sub.add_edge(START, "inner")
> sub.add_edge("inner", END)
sub_compiled = sub.compile()
# Вставляем как обычный узел в родительский граф
class ParentState(TypedDict):
out: str
> parent = StateGraph(ParentState)
> parent.add_node("sub_block", sub_compiled) # <- subgraph целиком
parent.add_edge(START, "sub_block")
parent.add_edge("sub_block", END)
app = parent.compile()
print(app.invoke({"out": ""}))
// note: snippet has 26 lines, card fits ~18
+54
View File
@@ -0,0 +1,54 @@
"""
Slide 51: Slide 24
Section 2: LangGraph 1.0
Source: slides/section2-langgraph/section2.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-051/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 51 ===
cfg = {"configurable": {"thread_id": "u1"}}
# values -- весь state после каждого super-step
> for snap in app.stream({"messages": []}, cfg, stream_mode="values"):
print(snap["messages"][-1].content)
# updates -- delta: только что вернул каждый узел
> for upd in app.stream({"messages": []}, cfg, stream_mode="updates"):
print(upd)
# events -- низкоуровневые события (start, end, error, interrupt)
> for ev in app.stream({"messages": []}, cfg, stream_mode="events"):
print(ev["event"], ev["name"])
# messages -- токены LLM по мере генерации
> for tok, meta in app.stream({"messages": []}, cfg, stream_mode="messages"):
print(tok.content, end="|")
# custom -- только то, что узлы пишут через get_stream_writer()
> for chunk in app.stream({"messages": []}, cfg, stream_mode="custom"):
print(chunk)
+62
View File
@@ -0,0 +1,62 @@
"""
Slide 52: Slide 25
Section 2: LangGraph 1.0
Source: slides/section2-langgraph/section2.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-052/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 52 ===
from langgraph.graph import StateGraph, START, END
from langgraph.config import get_stream_writer
from typing_extensions import TypedDict
class State(TypedDict):
total: int
def progress(state: State):
writer = get_stream_writer() # доступен только во время выполнения узла
> for i in range(3):
> writer({"progress": i, "phase": "thinking"})
> return {"total": 3}
g = StateGraph(State)
g.add_node("progress", progress)
g.add_edge(START, "progress")
g.add_edge("progress", END)
app = g.compile()
>
> # в UI -- только custom-чанки, без промежуточного state
for chunk in app.stream({"total": 0}, stream_mode="custom"):
print(chunk)
// note: snippet has 22 lines, card fits ~18
+56
View File
@@ -0,0 +1,56 @@
"""
Slide 53: Slide 26
Section 2: LangGraph 1.0
Source: slides/section2-langgraph/section2.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-053/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 53 ===
from langchain_openai import ChatOpenAI
from langchain.tools import tool
from langgraph.graph.message import add_messages
from typing import Annotated
from typing_extensions import TypedDict
@tool
def add(a: int, b: int) -> int:
"Add two numbers."
return a + b
tools = [add]
> llm = ChatOpenAI(model="gpt-4o-mini").bind_tools(tools)
class State(TypedDict):
messages: Annotated[list, add_messages]
def agent(state: State):
return {"messages": [llm.invoke(state["messages"])]}
def route(state: State) -> str:
> last = state["messages"][-1]
return "tools" if getattr(last, "tool_calls", None) else END
+54
View File
@@ -0,0 +1,54 @@
"""
Slide 54: Slide 27
Section 2: LangGraph 1.0
Source: slides/section2-langgraph/section2.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-054/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 54 ===
from langgraph.graph import StateGraph, START, END
from langgraph.prebuilt import ToolNode
# tools, llm, agent, route -- из предыдущего слайда
g = StateGraph(State)
g.add_node("agent", agent)
> g.add_node("tools", ToolNode(tools))
g.add_edge(START, "agent")
g.add_conditional_edges("agent", route, {"tools": "tools", END: END})
g.add_edge("tools", "agent")
> app = g.compile()
# Цикл: agent решает -> tools исполняет -> agent снова читает результат
> result = app.invoke({
> "messages": [{"role": "user", "content": "What is 2 + 3?"}]
})
print(result["messages"][-1].content)
+39
View File
@@ -0,0 +1,39 @@
"""
Slide 55: Slide 28
Section 2: LangGraph 1.0
Source: slides/section2-langgraph/section2.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-055/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 55 ===
# запуск: langgraph dev -- поднимает Studio на http://localhost:8123
+49
View File
@@ -0,0 +1,49 @@
"""
Slide 56: Slide 29
Section 2: LangGraph 1.0
Source: slides/section2-langgraph/section2.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-056/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 56 ===
# langgraph.json -- declarative config
> {
"graphs": {"agent": "./agent.py:graph"},
"env": "./.env",
"python_version": "3.11"
}
# CLI: локальный dev-сервер и deploy
langgraph dev # локальный API + Studio
> langgraph up # Docker-compose stack (Redis + API + Studio)
langgraph deploy # пуш в LangGraph Platform (managed)
+39
View File
@@ -0,0 +1,39 @@
"""
Slide 57: Slide 30
Section 2: LangGraph 1.0
Source: slides/section2-langgraph/section2.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-057/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# (No extractable code on this slide — visual-only or section divider)
print('Slide 57: Slide 30')
+60
View File
@@ -0,0 +1,60 @@
"""
Slide 58: Slide 31
Section 2: LangGraph 1.0
Source: slides/section2-langgraph/section2.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-058/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 58 ===
> import { StateGraph, START, END, Annotation } from "@langchain/langgraph";
> import { MemorySaver } from "@langchain/langgraph-checkpoint";
const State = Annotation.Root({
messages: Annotation({
reducer: (a, b) => a.concat(b),
default: () => [],
}),
});
const g = new StateGraph(State)
.addNode("echo", (s) => ({
messages: [{ role: "assistant", content: "echo: " + s.messages.at(-1).content }],
}))
.addEdge(START, "echo")
.addEdge("echo", END);
const app = g.compile({ checkpointer: new MemorySaver() });
> const cfg = { configurable: { thread_id: "t1" } };
const result = await app.invoke({ messages: [{ role: "user", content: "hi" }] }, cfg);
// note: snippet has 20 lines, card fits ~18
+39
View File
@@ -0,0 +1,39 @@
"""
Slide 59: Slide 32
Section 2: LangGraph 1.0
Source: slides/section2-langgraph/section2.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-059/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# (No extractable code on this slide — visual-only or section divider)
print('Slide 59: Slide 32')
+39
View File
@@ -0,0 +1,39 @@
"""
Slide 60: Slide 33
Section 2: LangGraph 1.0
Source: slides/section2-langgraph/section2.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-060/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# (No extractable code on this slide — visual-only or section divider)
print('Slide 60: Slide 33')
+39
View File
@@ -0,0 +1,39 @@
"""
Slide 61: Deep Agents 1.0
Section 3: Deep Agents
Source: slides/section3-deepagents/section3.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-061/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# (No extractable code on this slide — visual-only or section divider)
print('Slide 61: Deep Agents 1.0')
+39
View File
@@ -0,0 +1,39 @@
"""
Slide 62: Slide 2
Section 3: Deep Agents
Source: slides/section3-deepagents/section3.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-062/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# (No extractable code on this slide — visual-only or section divider)
print('Slide 62: Slide 2')
+56
View File
@@ -0,0 +1,56 @@
"""
Slide 63: Slide 3
Section 3: Deep Agents
Source: slides/section3-deepagents/section3.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-063/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 63 ===
// examples/hello.py:1-14
# One import, one call -- you get:
# - write_todos planning tool
# - ls / read_file / write_file / edit_file
# - glob, grep, execute (bash)
# - task tool for subagents
# - summarization middleware
from deepagents import create_deep_agent
>
> agent = create_deep_agent(
> model="openai:gpt-4.1",
> tools=[my_tool],
> system_prompt="...",
> )
// note: snippet has 14 lines, card fits ~10
+47
View File
@@ -0,0 +1,47 @@
"""
Slide 64: Slide 4
Section 3: Deep Agents
Source: slides/section3-deepagents/section3.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-064/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 64 ===
// setup.sh:1-5
pip install deepagents
# or, with uv:
uv add deepagents
# JS analogue:
npm install deepagents
// note: snippet has 5 lines, card fits ~3
+52
View File
@@ -0,0 +1,52 @@
"""
Slide 65: Slide 5
Section 3: Deep Agents
Source: slides/section3-deepagents/section3.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-065/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 65 ===
// examples/hello.py:1-12
from deepagents import create_deep_agent
> agent = create_deep_agent(
> model="openai:gpt-4.1",
> tools=[],
> system_prompt="You are a helpful assistant.",
)
result = agent.invoke({
"messages": "Write a haiku about Python"
})
print(result["messages"][-1].content)
+55
View File
@@ -0,0 +1,55 @@
"""
Slide 66: Slide 6
Section 3: Deep Agents
Source: slides/section3-deepagents/section3.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-066/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 66 ===
// examples/full_api.py:1-15
from deepagents import create_deep_agent
from deepagents.backends import FilesystemBackend
> agent = create_deep_agent(
> model="anthropic:claude-sonnet-4-5",
> tools=[my_tool],
> system_prompt="...",
> subagents=[researcher, writer],
> skills=["./skills/review.md"],
> backend=FilesystemBackend("./ws"),
> middleware=[my_hitl, my_logger],
> checkpointer=InMemorySaver(),
> store=InMemoryStore(),
> interrupt_on={"bash": True},
)
+56
View File
@@ -0,0 +1,56 @@
"""
Slide 67: Slide 7
Section 3: Deep Agents
Source: slides/section3-deepagents/section3.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-067/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 67 ===
// examples/system_prompt.py:1-16
SYSTEM_PROMPT = """
You are a senior backend engineer.
> WORKFLOW:
> 1. Plan with write_todos before non-trivial work.
> 2. Explore the codebase via ls / glob / grep first.
> 3. Use edit_file for surgical changes, write_file for new files.
> 4. Delegate research tasks to the "researcher" subagent.
5. Run tests via execute; never claim success without output.
CONSTRAINTS:
> - Do not modify files outside ./src.
> - Stop and ask the user if requirements are ambiguous.
"""
agent = create_deep_agent(model=..., system_prompt=SYSTEM_PROMPT)
+55
View File
@@ -0,0 +1,55 @@
"""
Slide 68: Slide 8
Section 3: Deep Agents
Source: slides/section3-deepagents/section3.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-068/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 68 ===
write_todos
ls
read_file
write_file
edit_file
glob
grep
execute
task
+51
View File
@@ -0,0 +1,51 @@
"""
Slide 69: Slide 9
Section 3: Deep Agents
Source: slides/section3-deepagents/section3.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-069/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 69 ===
// examples/fs_tools.py:1-11
# The agent calls these tools by name;
# you describe the goal in the prompt.
> PROMPT = """
> 1. Write src/hello.py with a greet(name) function.
> 2. Use edit_file to add a docstring to greet().
> 3. Use write_file to add tests/test_hello.py.
"""
agent = create_deep_agent(model="openai:gpt-4.1")
agent.invoke({"messages": PROMPT})
+54
View File
@@ -0,0 +1,54 @@
"""
Slide 70: Slide 10
Section 3: Deep Agents
Source: slides/section3-deepagents/section3.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-070/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 70 ===
// examples/write_todos.py:1-12
write_todos(
> todos=[
> {"content": "Read repo structure", "status": "in_progress",
> "activeForm": "Reading repo structure"},
> {"content": "Implement greet()", "status": "pending",
> "activeForm": "Implementing greet()"},
> {"content": "Add pytest cases", "status": "pending",
> "activeForm": "Adding pytest cases"},
> ]
)
# Status: pending | in_progress | completed
# activeForm: present-continuous shown in UI
// note: snippet has 12 lines, card fits ~10
+39
View File
@@ -0,0 +1,39 @@
"""
Slide 71: Slide 11
Section 3: Deep Agents
Source: slides/section3-deepagents/section3.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-071/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# (No extractable code on this slide — visual-only or section divider)
print('Slide 71: Slide 11')
+50
View File
@@ -0,0 +1,50 @@
"""
Slide 72: Slide 12
Section 3: Deep Agents
Source: slides/section3-deepagents/section3.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-072/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 72 ===
// examples/task_call.py:1-10
# When the main agent emits a tool call like:
> task(
> subagent_type="researcher",
> description="Find papers on RAG evaluation",
> prompt="Search arXiv for 2025-2026 RAG evaluation surveys.
> Return a 150-word summary with 3 citations.",
)
# Deep Agents spins up a fresh deep agent with the researcher profile,
# runs it to completion, and returns only the final message.
+65
View File
@@ -0,0 +1,65 @@
"""
Slide 73: Slide 13
Section 3: Deep Agents
Source: slides/section3-deepagents/section3.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-073/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 73 ===
// examples/subagents.py:1-23
from deepagents import create_deep_agent
researcher = {
> "name": "researcher",
> "description": "Does deep web research, returns citations",
> "system_prompt": "You are a research specialist. Always cite sources.",
> "tools": [web_search], # optional, can be []
}
writer = {
> "name": "writer",
> "description": "Polishes prose into a final report",
> "system_prompt": "You are a writing specialist.",
> "tools": [],
}
agent = create_deep_agent(
model="openai:gpt-4.1",
> tools=[],
> subagents=[researcher, writer],
> )
>
agent.invoke({"messages": "Research quantum computing and write a 200-word summary."})
// note: snippet has 23 lines, card fits ~16
+58
View File
@@ -0,0 +1,58 @@
"""
Slide 74: Slide 14
Section 3: Deep Agents
Source: slides/section3-deepagents/section3.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-074/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 74 ===
context = [
user task,
summary from researcher,
summary from writer
]
task("researcher")
context = [
full web_search results,
all 14 sources,
notes, drafts, citations
]
return: 150-word summary
context = [
researcher summary,
original user task
]
return: polished 200-word report
+49
View File
@@ -0,0 +1,49 @@
"""
Slide 75: Slide 15
Section 3: Deep Agents
Source: slides/section3-deepagents/section3.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-075/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 75 ===
// examples/virtual_fs.py:1-9
# Inspect the virtual filesystem after a run:
result = agent.invoke({"messages": "Summarize repo"})
>
> files = result.get("files", {})
> for path, doc in files.items():
> print(f"{path}: {len(doc.get('content', []))} bytes")
# /repo/src/main.py: 421 bytes
# /repo/README.md: 1804 bytes
+45
View File
@@ -0,0 +1,45 @@
"""
Slide 76: Slide 16
Section 3: Deep Agents
Source: slides/section3-deepagents/section3.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-076/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 76 ===
before_model
after_model
before_tool
after_tool
+60
View File
@@ -0,0 +1,60 @@
"""
Slide 77: Slide 17
Section 3: Deep Agents
Source: slides/section3-deepagents/section3.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-077/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 77 ===
// examples/middleware.py:1-18
from langchain.agents.middleware import AgentMiddleware
from deepagents import create_deep_agent
class LoggerMiddleware(AgentMiddleware):
> def before_model(self, state, runtime):
> print(f"[model] {len(state['messages'])} msgs in")
> return state
>
> def after_tool(self, state, runtime, tool_result):
> print(f"[tool] {tool_result.tool_call_id} -> {len(str(tool_result.content))} chars")
return state
agent = create_deep_agent(
model="openai:gpt-4.1",
middleware=[LoggerMiddleware(), HumanInTheLoopMiddleware(
> interrupt_on={"execute": True}, # ask before running bash
> )],
> )
// note: snippet has 18 lines, card fits ~16
+39
View File
@@ -0,0 +1,39 @@
"""
Slide 78: Slide 18
Section 3: Deep Agents
Source: slides/section3-deepagents/section3.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-078/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# (No extractable code on this slide — visual-only or section divider)
print('Slide 78: Slide 18')
+62
View File
@@ -0,0 +1,62 @@
"""
Slide 79: Slide 19
Section 3: Deep Agents
Source: slides/section3-deepagents/section3.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-079/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 79 ===
// examples/composite_backend.py:1-20
from deepagents import create_deep_agent
from deepagents.backends import (
CompositeBackend, FilesystemBackend, StoreBackend
)
from langgraph.store.memory import InMemoryStore
store = InMemoryStore() # or PostgresStore in prod
backend = CompositeBackend(
default=FilesystemBackend(root_dir="./workspace"),
routes={
> "/memory/": StoreBackend(store=store, namespace=("agent", "kb")),
> "/scratch/": FilesystemBackend(root_dir="/tmp/scratch"),
> },
> )
agent = create_deep_agent(model=..., backend=backend)
# /workspace/notes.md -> local disk
# /memory/lessons.md -> Postgres, shared across sessions
> # /scratch/tmp.py -> ephemeral tmpfs
// note: snippet has 20 lines, card fits ~16
+65
View File
@@ -0,0 +1,65 @@
"""
Slide 80: Slide 20
Section 3: Deep Agents
Source: slides/section3-deepagents/section3.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-080/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 80 ===
// examples/hitl.py:1-23
from langchain.agents.middleware import HumanInTheLoopMiddleware
from deepagents import create_deep_agent
from langgraph.checkpoint.memory import InMemorySaver
from langgraph.types import Command
agent = create_deep_agent(
model="openai:gpt-4.1",
checkpointer=InMemorySaver(),
> middleware=[HumanInTheLoopMiddleware(
> interrupt_on={
> "execute": True, # bash -- always ask
> "write_file": True, # disk writes -- always ask
> "task": False, # subagents -- run unattended
> },
)],
)
cfg = {"configurable": {"thread_id": "user-42"}}
try:
agent.invoke({"messages": "deploy to staging"}, cfg)
except InterruptedError:
decision = ask_user("Approve execute()?") # your UI
agent.invoke(Command(resume=decision), cfg)
// note: snippet has 23 lines, card fits ~15
+60
View File
@@ -0,0 +1,60 @@
"""
Slide 81: Slide 21
Section 3: Deep Agents
Source: slides/section3-deepagents/section3.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-081/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 81 ===
// examples/streaming.py:1-18
cfg = {"configurable": {"thread_id": "user-42"}}
# 1. Stream model tokens as they arrive
> for token, meta in agent.stream(
> {"messages": "..."}, cfg,
> stream_mode="messages",
):
print(token.content, end="", flush=True)
# 2. Stream state updates per node
for chunk in agent.stream(
> {"messages": "..."}, cfg,
> stream_mode="updates",
> ):
print(chunk) # {"model": {...}, "tools": {...}}
# 3. Subagent streams are surfaced as
# {"subagent": {"name": "researcher", "chunk": ...}}
// note: snippet has 18 lines, card fits ~16
+48
View File
@@ -0,0 +1,48 @@
"""
Slide 82: Slide 22
Section 3: Deep Agents
Source: slides/section3-deepagents/section3.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-082/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 82 ===
// examples/langsmith.sh:1-8
export LANGSMITH_TRACING=true
export LANGSMITH_API_KEY=lsv2_...
export LANGSMITH_PROJECT=deepagents-evals
python my_deep_agent.py
# -> all runs visible in smith.langchain.com
# -> subagent runs nested under the parent
# -> token usage, latency, tool errors captured
+66
View File
@@ -0,0 +1,66 @@
"""
Slide 83: Slide 23
Section 3: Deep Agents
Source: slides/section3-deepagents/section3.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-083/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 83 ===
// examples/research_agent.py:1-24
from langchain.tools import tool
from deepagents import create_deep_agent
@tool
def arxiv_search(query: str, max_results: int = 5) -> str:
"""Search arXiv for papers matching the query."""
import arxiv
client = arxiv.Client()
results = list(client.results(arxiv.Search(query=query, max_results=max_results)))
return "\n\n".join(
f"{r.title}\n{r.summary[:300]}..." for r in results
)
agent = create_deep_agent(
model="openai:gpt-4.1",
tools=[arxiv_search],
system_prompt=("You are a research assistant. Always cite paper titles and arXiv IDs."),
> subagents=[{
> "name": "summarizer",
> "description": "Compresses paper abstracts into a paragraph",
> "system_prompt": "You are a precise summarizer.",
> "tools": [],
> }],
> )
// note: snippet has 24 lines, card fits ~16
+59
View File
@@ -0,0 +1,59 @@
"""
Slide 84: Slide 24
Section 3: Deep Agents
Source: slides/section3-deepagents/section3.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-084/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 84 ===
// examples/coding_agent.py:1-17
from deepagents import create_deep_agent
from deepagents.backends import SandboxBackend
> agent = create_deep_agent(
> model="anthropic:claude-sonnet-4-5",
> backend=SandboxBackend(
> provider="daytona", # or modal / runloop
> api_key=os.environ["DAYTONA_API_KEY"],
> image="python:3.12-slim",
> ),
> system_prompt=("You are a coding agent. Always run tests after edits. Stop and ask if requirements are ambiguous."),
)
agent.invoke({"messages": "Add a /healthz endpoint to the FastAPI app, with tests."})
# Daytona/Modal/Runloop execute code in an isolated container;
# the local process never sees a stray rm -rf.
// note: snippet has 17 lines, card fits ~16
+53
View File
@@ -0,0 +1,53 @@
"""
Slide 85: Slide 25
Section 3: Deep Agents
Source: slides/section3-deepagents/section3.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-085/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 85 ===
// examples/deepagentsjs.ts:1-13
// TypeScript analogue (deepagentsjs)
import { createDeepAgent } from "deepagents";
import { tool, z } from "@langchain/core/tools";
const search = tool(
async ({ q }) => fetch("/api/search?q=" + q).then(r => r.text()),
{ name: "search", schema: z.object({ q: z.string() }) },
);
> const agent = await createDeepAgent({
> model: "openai:gpt-4.1",
> tools: [search],
> });
+39
View File
@@ -0,0 +1,39 @@
"""
Slide 86: Slide 26
Section 3: Deep Agents
Source: slides/section3-deepagents/section3.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-086/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# (No extractable code on this slide — visual-only or section divider)
print('Slide 86: Slide 26')
+39
View File
@@ -0,0 +1,39 @@
"""
Slide 87: Open SWE: async coding agent
Section 4: Open SWE
Source: slides/section4-openswe/section4.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-087/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# (No extractable code on this slide — visual-only or section divider)
print('Slide 87: Open SWE: async coding agent')
+52
View File
@@ -0,0 +1,52 @@
"""
Slide 88: Slide 2
Section 4: Open SWE
Source: slides/section4-openswe/section4.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-088/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 88 ===
// meta: open-swe repo:1-12
# github.com/langchain-ai/open-swe
stars: ~10k
commits: 971+
license: MIT
language: Python + TypeScript
announce: 08.2025
rewrite: 03.2026
# blog.langchain.com/open-swe
# INSTALLATION.md
# CUSTOMIZATION.md
+65
View File
@@ -0,0 +1,65 @@
"""
Slide 89: Slide 3
Section 4: Open SWE
Source: slides/section4-openswe/section4.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-089/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 89 ===
Slack / Linear / GitHub / Web UI
prompt + middleware (HITL, approval)
subagents + middleware
AGENTS.md из репозитория
execute, fetch_url, linear_comment, slack_thread_reply
Modal / Daytona / Runloop / LangSmith
create_deep_agent (Deep Agents)
// open_swe/__init__.py:1-11
from open_swe.agent import create_agent
from open_swe.middleware import (
check_message_queue_before_model,
notify_step_limit_reached,
open_pr_if_needed,
ToolErrorMiddleware,
)
from open_swe.sandbox import (
SandboxBackend,
ModalBackend, DaytonaBackend,
)
+51
View File
@@ -0,0 +1,51 @@
"""
Slide 90: Slide 4
Section 4: Open SWE
Source: slides/section4-openswe/section4.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-090/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 90 ===
// examples/minimal_agent.py:1-11
from deepagents import create_deep_agent
from open_swe.sandbox import DaytonaBackend
> agent = create_deep_agent(
model="anthropic:claude-opus-4-6",
tools=[execute, fetch_url,
linear_comment,
> slack_thread_reply],
> backend=DaytonaBackend(api_key="..."),
middleware=[open_pr_if_needed],
)
+59
View File
@@ -0,0 +1,59 @@
"""
Slide 91: Slide 5
Section 4: Open SWE
Source: slides/section4-openswe/section4.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-091/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 91 ===
// open_swe/prompts.py:1-9
from pathlib import Path
def construct_system_prompt(
repo_dir, base_prompt
):
agents_md = Path(repo_dir) / "AGENTS.md"
extra = agents_md.read_text() if
agents_md.exists() else ""
return base_prompt + extra
// note: snippet has 9 lines, card fits ~6
// AGENTS.md:1-5
# AGENTS.md (repo root)
- use uv, not pip
- run pytest before commit
- never push to main directly
+53
View File
@@ -0,0 +1,53 @@
"""
Slide 92: Slide 6
Section 4: Open SWE
Source: slides/section4-openswe/section4.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-092/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 92 ===
// examples/audit_middleware.py:1-13
from langchain.agents.middleware import (
AgentMiddleware,
)
> class AuditMiddleware(AgentMiddleware):
> def after_model(self, state, runtime):
> runtime.logger.info(
> f"step={state.get("step")}"
)
return state
def before_model(self, state, runtime):
return state # inject reminder
+77
View File
@@ -0,0 +1,77 @@
"""
Slide 93: Slide 7
Section 4: Open SWE
Source: slides/section4-openswe/section4.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-093/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 93 ===
ModalBackend
token_id + token_secret
per-second + GB-s
yes (volume)
Python-first, GPU-доступный
DaytonaBackend
api_key
per-session
yes (volume)
default в README
RunloopBackend
api_key
per-second
yes (volume)
dev-цикл, snapshot/restart
LangSmithBackend
LANGSMITH_API_KEY
через LangSmith
через LS
уже платите за LangSmith
+87
View File
@@ -0,0 +1,87 @@
"""
Slide 94: Slide 8
Section 4: Open SWE
Source: slides/section4-openswe/section4.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-094/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 94 ===
// open_swe/sandbox/__init__.py:1-12
from open_swe.sandbox import (
ModalBackend,
DaytonaBackend,
RunloopBackend,
LangSmithBackend,
)
# Modal (Python-first, GPU)
backend = ModalBackend(
token_id="..."
token_secret="..."
)
// examples/my_internal_backend.py:1-11
# свой backend: devbox-пул
from open_swe.sandbox import (
SandboxBackend,
)
>
class MyInternalBackend(SandboxBackend):
def execute(self, cmd):
> return self._run(cmd)
>
def read_file(self, p):
> return self._fetch(p)
// examples/my_internal_backend.py:1-16
# свой backend: devbox-пул
from open_swe.sandbox import (
SandboxBackend,
)
class MyInternalBackend(
SandboxBackend
):
def __init__(self, conn):
self.conn = conn
>
> def execute(self, cmd):
> return self._run(cmd)
>
> def read_file(self, p):
> return self._fetch(p)
// note: snippet has 16 lines, card fits ~15
+53
View File
@@ -0,0 +1,53 @@
"""
Slide 95: Slide 9
Section 4: Open SWE
Source: slides/section4-openswe/section4.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-095/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 95 ===
// INSTALLATION.md: step 1:1-5
# 1. prerequisites
python --version # >= 3.11
node --version # >= 20
uv --version # или pip
docker --version # для dev
// INSTALLATION.md: step 2:1-5
# 2. clone + install
git clone https://github.com/
langchain-ai/open-swe.git
cd open-swe
uv sync # или pip install -e .
+53
View File
@@ -0,0 +1,53 @@
"""
Slide 96: Slide 10
Section 4: Open SWE
Source: slides/section4-openswe/section4.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-096/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 96 ===
// INSTALLATION.md: steps 3-5:1-13
# 3. backend (FastAPI)
uv run apps/open-swe/main.py
# -> :8000
# 4. UI (TanStack Start + Vite)
cd apps/open-swe-ui
pnpm install && pnpm dev
# -> :3000
# 5. smoke-test
curl -X POST :8000/webhooks/slack \
-d '{"text":"@open-swe hello"}'
# -> {"thread_id": "..."}
+53
View File
@@ -0,0 +1,53 @@
"""
Slide 97: Slide 11
Section 4: Open SWE
Source: slides/section4-openswe/section4.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-097/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 97 ===
// config/github-app-manifest.yaml:1-13
# github-app-manifest.yaml
name: open-swe-internal
> url: https://open-swe.example.com
> hook_attributes:
> url: https://open-swe.example.com/
> webhooks/github
> events:
> - issue_comment
> - pull_request
- pull_request_review
default_permissions:
contents: write
pull_requests: write
+50
View File
@@ -0,0 +1,50 @@
"""
Slide 98: Slide 12
Section 4: Open SWE
Source: slides/section4-openswe/section4.pptx
Сгенерировано автоматически из slide-NN.js / sectionN.pptx.
Паттерн провайдера скопирован из
bro-js/agents/teacher/assistant/src/angry_teacher/llm.py.
Запуск:
cd langchain-evolution-deck
cp .env.example .env # заполни OPENAI_API_KEY
python examples/slide-098/script.py
"""
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(
# model="openrouter/free",
# model="qwen/qwen3.5-35b-a3b",
model="openai/gpt-oss-20b",
# model="nvidia/nemotron-3-nano",
# model="qwen/qwen3.5-9b",
base_url="https://llm.brojs.ru/v1",
# base_url="https://api.minimax.io/v1",
# base_url="http://0.0.0.0:8090/v1",
# base_url="https://openrouter.ai/api/v1",
# api_key=os.getenv("MINIMAX_API_KEY"),
api_key=(os.getenv("OPENAI_API_KEY") or "").strip() or None,
temperature=0.7,
stream_usage=True,
)
# === Code from slide 98 ===
// .env:1-10
# .env (НЕ коммитить)
LANGSMITH_TRACING=true
LANGSMITH_ENDPOINT=https://
api.smith.langchain.com
LANGSMITH_API_KEY=lsv2_...
LANGSMITH_PROJECT=open-swe-prod
LANGSMITH_SNAPSHOT=true
# для sandbox-прокси:
LANGSMITH_SANDBOX_BACKEND=true

Some files were not shown because too many files have changed in this diff Show More