Новое:Talanto осенью: поиск с цифрами, вакансия по шагам и каталог компаний

+1 210новых вакансий за сутки·93 612вакансий открыто сейчас·Новое:Talanto осенью: поиск с цифрами, вакансия по шагам и каталог компаний

Новые вакансии в TelegramРаботодателям
Talanto
Вакансии
Компании7 266
РезюмеAIПодготовкаСтатьи
BoostТарифыBoost
Войти

Не нашли подходящее?

Пусть нужная вакансия найдёт вас сама.

  1. Подборка в TelegramНовые вакансии по вашему фильтру — сразу в бота.Подключить
  2. Мэтчи по резюмеЗагрузите резюме — покажем, где вы подходите лучше всего.Загрузить
  3. Сохранить фильтрНастройте поиск один раз и возвращайтесь к новым вакансиям.Настроить
Что нового на TalantoTalanto осенью: поиск с цифрами, вакансия по шагам и каталог компаний

Для работодателей

Опубликуйте вакансию — отклики придут в ваш кабинет.

  1. Вакансиябесплатно
  2. Откликиконтакты бесплатно
  3. Наймэтапы и интервью

40 компаний публикуют вакансии напрямую · 4 401 кандидат открыт к предложениям

Разместить вакансию

Популярные направления

Все подборки
  • Python17 126
  • Облачные технологии14 083
  • QA вакансии3 456
  • Backend вакансии2 115
  • Инженер данных1 809
  • Продакт-менеджер1 261

Разработка

  • Android1 862
  • iOS1 700
  • Fullstack вакансии986
  • AI вакансии950
  • Frontend вакансии744
  • Mobile вакансии44

По стеку

  • Go8 688
  • Java6 537
  • Node.js2 026
  • .NET1 722
  • Kotlin1 611
  • Rust1 458
  • C#710
  • PHP682
  • C++571

DevOps и инфраструктура

  • Kubernetes7 772
  • DevOps вакансии6 054
  • Linux-инфраструктура5 493
  • Terraform / IaC4 275
  • CI/CD3 239
  • Мониторинг и Observability1 790
  • SRE568
  • Кибербезопасность458

Аналитика и данные

  • Data Scientist1 143
  • Бизнес-аналитик923
  • Аналитик данных857
  • Системный аналитик152

Другие направления

  • Проджект-менеджер620
  • UI/UX дизайн146
  • Ручное тестирование14

По регионам

  • Вакансии в США44 276
  • Вакансии в Европе23 819
  • Вакансии в Канаде4 471
  • Работа в России3 904

По формату

  • Удалённые вакансии74 928
  • Релокация в США44 273
  • Гибридная работа12 388
  • Офисная работа7 083

По уровню

  • Senior вакансии42 625
  • Middle вакансии20 854
  • Junior вакансии6 721

Сейчас нанимают

Все компании
  • Wise190 вакансий
  • Rakuten189 вакансий
  • ASML166 вакансий
  • Grab137 вакансий
  • Celonis39 вакансий
  • Spotify37 вакансий
  • Adyen28 вакансий
  • Infobip28 вакансий
  • Monzo20 вакансий
  • Darktrace16 вакансий

Вакансии из 344 источников: карьерные страницы компаний и джоб-борды.

КомпанииО насНовостиПубличная офертаУсловия использованияПолитика конфиденциальностиПоддержка
←К теме LangChainВсе вопросы
LangChainMiddleКодинг

Как работают RunnablePassthrough и RunnableParallel в LCEL?

В закладки
Сначала попробуйте ответить сами30 секунд
Сравнить с ответом ↓

RunnablePassthrough передаёт вход без изменений (или добавляет поля через .assign()), RunnableParallel выполняет несколько Runnable параллельно и собирает результаты в словарь.

RunnablePassthrough — прозрачная передача данных

Передаёт входные данные следующему шагу без изменений. Используется когда нужно сохранить оригинальный вход для дальнейшего использования в цепочке.

from langchain_core.runnables import RunnablePassthrough
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser

# Базовое использование — просто передаёт строку дальше
passthrough = RunnablePassthrough()
result = passthrough.invoke("hello")  # -> "hello"

llm = ChatOpenAI(model="gpt-4o")
prompt = ChatPromptTemplate.from_messages([
    ("system", "Answer the question using the context.\nContext: {context}"),
    ("human", "{question}"),
])

# RAG-паттерн: question передаётся через passthrough,
# одновременно идёт в retriever для поиска
rag_chain = (
    {
        "context": retriever,           # retriever получает вопрос
        "question": RunnablePassthrough()  # вопрос передаётся дальше как есть
    }
    | prompt
    | llm
    | StrOutputParser()
)

result = rag_chain.invoke("What is vector search?")

RunnablePassthrough и RunnableParallel в LCEL

LCEL (LangChain Expression Language) строит цепочки через оператор |. Два специальных объекта — RunnablePassthrough и RunnableParallel — решают задачи маршрутизации и трансформации данных внутри цепочки.

RunnablePassthrough.assign() — добавление полей

.assign() добавляет новые ключи в словарь, не удаляя существующие. Это основной способ обогатить контекст по ходу цепочки.

from langchain_core.runnables import RunnablePassthrough

# Исходный словарь: {"question": "What is Python?"}
# После assign добавляется поле "context"
chain = (
    RunnablePassthrough.assign(
        context=lambda x: retriever.invoke(x["question"]),
        timestamp=lambda x: "2026-05-20",
    )
    | prompt  # получает {"question": ..., "context": ..., "timestamp": ...}
    | llm
    | StrOutputParser()
)

result = chain.invoke({"question": "Explain LangChain"})
# prompt получил все три поля

RunnableParallel — параллельное выполнение

Запускает несколько Runnable одновременно (в потоках) и собирает результаты в словарь. Ключи словаря становятся именами результатов.

from langchain_core.runnables import RunnableParallel
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser

llm = ChatOpenAI(model="gpt-4o")

# Два промпта выполняются параллельно
positive_prompt = ChatPromptTemplate.from_messages([
    ("human", "List 3 advantages of {technology}")
])
negative_prompt = ChatPromptTemplate.from_messages([
    ("human", "List 3 disadvantages of {technology}")
])

parallel_analysis = RunnableParallel(
    pros=(positive_prompt | llm | StrOutputParser()),
    cons=(negative_prompt | llm | StrOutputParser()),
)

result = parallel_analysis.invoke({"technology": "Python"})
print(result["pros"])   # Список преимуществ
print(result["cons"])   # Список недостатков
# Оба LLM-вызова выполнились параллельно!

Краткий синтаксис — словарный литерал

В LCEL словарь автоматически преобразуется в RunnableParallel:

# Эти записи эквивалентны:

# Явный RunnableParallel
chain1 = RunnableParallel({"a": step_a, "b": step_b}) | final_step

# Сокращённый синтаксис через словарь
chain2 = {"a": step_a, "b": step_b} | final_step

# Комбинация всех инструментов
full_rag = (
    {"context": retriever, "question": RunnablePassthrough()}
    | RunnablePassthrough.assign(char_count=lambda x: len(x["question"]))
    | prompt
    | llm
    | StrOutputParser()
)

Реальный пример: multi-query retrieval

from langchain_core.runnables import RunnableParallel, RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser

# Генерируем 3 варианта запроса параллельно
rephrase_prompt = ChatPromptTemplate.from_messages([
    ("human", "Generate {n} different versions of: {question}")
])

multi_query_chain = (
    RunnableParallel(
        original=RunnablePassthrough(),
        v1=({"question": RunnablePassthrough(), "n": lambda _: 1} | rephrase_prompt | llm | StrOutputParser()),
        v2=({"question": RunnablePassthrough(), "n": lambda _: 1} | rephrase_prompt | llm | StrOutputParser()),
    )
    | (lambda x: [x["original"], x["v1"], x["v2"]])  # Объединяем
)

Подводные камни

  • RunnableParallel выполняется в потоках, не в asyncio — при sync вызове используются ThreadPoolExecutor; не подходит для CPU-heavy задач.
  • assign() мутирует входной словарь по ссылке — если в lambda изменить x, это влияет на другие ветки; создавайте новые объекты в lambda.
  • Порядок ключей в RunnableParallel не гарантирован — обращайтесь к результатам по именам ключей, не по индексу.
  • RunnablePassthrough без аргументов копирует весь вход — если вход — большой словарь с эмбеддингами, это лишняя копия памяти; передавайте только нужные поля через lambda.
  • Исключение в одной ветке RunnableParallel отменяет все — нет встроенной обработки частичных отказов; оборачивайте ветки в RunnableLambda с try/except.
  • Nested RunnableParallel теряет stream() — стриминг работает только по линейной цепочке; при параллельном выполнении стриминг буферизуется до завершения всех веток.

Типичные ошибки

  • Объяснять runnable passthrough parallel только синтаксисом без shape, dtype, состояния или режима выполнения.
  • Игнорировать leakage, воспроизводимость, пустые входы и скрытые копии данных.
  • Не проверять production-симптомы: latency, память, ретраи, дрейф качества и несовпадение версий.

Что проверяет интервьюер

  • Может ли связать runnable passthrough parallel с реальным контрактом входов и выходов.
  • Упоминает ли тесты, метрики, reproducibility и диагностику ошибок.
  • Видит ли различие между demo-кодом в ноутбуке и production-пайплайном.

Как вы знаете этот вопрос?

Проверить себя по теме LangChain →

Источники

  • https://docs.langchain.com/oss/python/langchain/models
←Предыдущий вопросКак использовать middleware в LangChain v1 для auth, observability и enforcement политик?Следующий вопрос→Как проектировать guardrails, structured output и retries для production LLM-app?

Связанные темы

LangChaindata-aillm-orchestrationtool-calling

Частые вопросы на собеседовании

  • Как работают инструменты (tools) в LangChain и как создать кастомный инструмент?
  • Что такое RAG (Retrieval-Augmented Generation) и как реализовать его с помощью LangChain?
  • В чём разница между invoke(), stream() и batch() в интерфейсе Runnable в LangChain?
  • Что такое LCEL (LangChain Expression Language) и как он использует оператор | для компоновки цепочек?