58174
Всё самое интересное из мира Python Связь: @devmangx РКН: https://clck.ru/3GMMF6
ML Engineer, LLM Engineer держите: TorchCode
Платформа с задачами для практики по базовым реализациям на PyTorch и вопросам по Transformer, которые часто встречаются на собеседованиях.
→ Собирает в 39 структурированных задачах типовые для ML-собеседований реализации операторов, модулей и архитектур на PyTorch.
→ Дает автопроверку, проверку градиентов, замер времени и мгновенный фидбек, чтобы практика больше напоминала LeetCode для собеседований.
→ Построена на базе Jupyter Notebook, при этом поддерживает сброс в один клик, подсказки, эталонные решения и трекинг прогресса.
→ Покрывает такие частые темы, как ReLU, Softmax, LayerNorm, Attention, RoPE, Flash Attention, LoRA, MoE и другие.
→ Поддерживает онлайн-режим через Hugging Face Spaces, открытие отдельных задач в Google Colab и локальный запуск через Docker.
👉 @PythonPortal
OpenAI опубликовала работу, в которой доказывается, что ChatGPT будет выдумывать всегда. 😖
Не иногда. Не до следующего обновления. Всегда. Они доказали это математически.
Даже при идеальных обучающих данных и неограниченной вычислительной мощности AI-модели всё равно будут уверенно говорить вещи, которые полностью ложны. Это не баг, который они пытаются пофиксить. Это фундаментально встроено в принцип работы таких систем.
И их собственные цифры довольно жёсткие. Рассуждающая модель o1 от OpenAI галлюцинирует в 16% случаев. Более новая o3? 33%. Их новейшая o4-mini? 48%. То есть почти половина того, что говорит их самая свежая модель, может быть выдумкой. Более «умные» модели на самом деле становятся хуже в плане правдивости.
Вот почему это нельзя исправить. Языковые модели работают, предсказывая следующее слово на основе вероятности. Когда они сталкиваются с неопределённостью, они не ставят ответ на паузу. Не помечают её. Они просто угадывают. И делают это с полной уверенностью, потому что именно этому их и обучали.
Исследователи посмотрели на 10 крупнейших AI-бенчмарков, которые используются для оценки качества таких моделей. В 9 из 10 случаев ответ I don't know получает ту же оценку, что и полностью неправильный ответ: ноль баллов. Вся система тестирования буквально наказывает честность и поощряет угадывание.
Поэтому AI выучил оптимальную стратегию: всегда угадывать. Никогда не признавать неопределённость. Звучать уверенно, даже когда он всё это выдумывает.
Какое решение предлагает OpenAI? Заставить ChatGPT отвечать I don't know, когда он не уверен. Но их собственная математика показывает, что тогда примерно 30% ваших запросов будут оставаться без ответа. Представьте: вы спрашиваете ChatGPT о чём-то, и примерно в трёх случаях из десяти получаете Я недостаточно уверен, чтобы ответить. Пользователи ушли бы практически сразу. То есть решение существует, но оно убило бы продукт.
И это не только проблема OpenAI. DeepMind и Tsinghua University независимо пришли к тому же выводу. Три ведущие AI-лаборатории мира, работая по отдельности, сошлись в одном: это навсегда.
Каждый раз, когда ChatGPT даёт вам ответ, задавайте себе вопрос: это правда или просто уверенная догадка?
👉 @PythonPortal
Новый PEP
Ограничения в софтверной инженерии созданы, чтобы их ломать. Годами меня бесил разрыв между Python и TypeScript: у одного невероятно динамичный и мощный рантайм, у другого невероятно динамичная и мощная система типов.
Так почему бы не совместить и то, и другое? 🔥
Встречайте PEP 827, результат годового ресерча о том, что нужно, чтобы прокачать type checking в Python до уровня его динамичности.
Вот как можно реализовать Record, сравнив варианты бок о бок:
TypeScript
type Record<K extends string, V> = {
[P in K]: V
}
// так что...
type Fruit = Record<
'apple' | 'banana' | 'orange',
string
>
// развернется в
//
// {
// apple: string;
// banana: string;
// orange: string;
// }type Record[K, V] = NewTypedDict[
*[Member[k, V] for k in Iter[FromUnion[K]]]
]
# так что...
type Fruit = Record[
Literal["apple", "banana", "orange"],
str
]
# развернется в
#
# class <Fruit>:
# apple: str
# banana: str
# orange: str
Pick:type Pick<T, K extends keyof T> = {
[P in K]: T[P]
}type Pick[T, K] = NewProtocol[*[
p for p in Iter[Attrs[T]]
if IsAssignable[p.name, K]
]]
Omit. Обрати внимание: версия на Python по сути не изменилась по сравнению с реализацией Pick, в отличие от TS.ts id="5ehk8a"
type Omit<T, K extends keyof T> = {
[P in Exclude<keyof T, K>]: T[P]
}
py id="g6u8k1"
type Omit[T, K] = NewProtocol[*[
p for p in Iter[Attrs[T]]
if not IsAssignable[p.name, K]
]]
Гвидо ван Россум (отец Python) выпустил новую версию typeagent, Python-библиотеки, над которой он работал с середины прошлого года, и все больше делал это вместе с Claude. Она реализует память для агентов.
Установка: pip install typeagent.
CHANGELOG.md
👉 @PythonPortal
10 библиотек Python для генеративного ИИ, которые нужно освоить в 2026 году
👉 @PythonPortal
Немного базы Python. День 10 - Абсолютное значение (модуль) числа
Допустим, у тебя есть отрицательное число и ты хочешь получить его абсолютное значение. Для этого можно использовать функцию abs(). Функция abs() возвращает абсолютное значение любого числа (положительного, отрицательного и комплексного). Ниже показано, как получить список абсолютных значений из списка, где есть и отрицательные, и положительные числа. Используем list comprehension.
list1 = [-12, -45, -67, -89, 34, 67, -13]
print([abs(num) for num in list1])
[12, 45, 67, 89, 34, 67, 13]
abs() можно применять к числу с плавающей точкой, и она вернет абсолютное значение. Смотри ниже:num = -23.12
print(abs(num))
23.12
fabs() из модуля math. Эта функция всегда возвращает float.import math
num = -23.12
absolute_value = math.fabs(num)
absolute_value
23.12
lambda, чтобы превратить отрицательное число в модуль. Код ниже проверяет, меньше ли x нуля (то есть отрицательное ли значение). Если да, возвращает -x, по сути убирая минус и делая число положительным. Если x не отрицательное (больше или равно 0), возвращает x как есть.num = -23.12
absolute_value = (lambda x: -x if x < 0 else x)(num)
absolute_value
23.12
Всегда пиши код так, будто тот, кому потом его поддерживать, это буйный психопат, который знает, где ты живешь.
Python-совет по дизайну: используй @property только для O(1) операций
Люди обычно ожидают, что всё, что выглядит как доступ к атрибуту, работает быстро.
Не хочется же жать Ctrl-C на чтении атрибута, потому что там спрятан расчёт уровня Deep Thought на 7,5 миллионов лет:
>>> life.meaning
42
Немного базы Python. День 8 - Сделать вложенный список плоским
Я покажу вам три (3) способа, как можно развернуть двумерный список. В первом методе используется цикл for, во втором используется модуль itertools, а в третьем используется списковое включение (list comprehension).
⚙️ С помощью цикла for:
Для этого метода мы используем вложенный цикл for. Внешний цикл проходит по внутренним спискам, а внутренний цикл обращается к элементам во внутренних списках.
# In [19]:
list1 = [[1, 2, 3],[4, 5, 6]]
newlist = []
for list2 in list1:
for j in list2:
newlist.append(j)
print(newlist)
[1, 2, 3, 4, 5, 6]
itertools.chain.from_iterable() из модуля itertools можно использовать, чтобы развернуть вложенный список. Этот метод может не подойти для списков с глубокой вложенностью.# In [20]:
import itertools
list1 = [[1, 2, 3],[4, 5, 6]]
flat_list = list(itertools.chain.from_iterable(list1))
print(flat_list)
[1, 2, 3, 4, 5, 6]
itertools или писать обычный цикл for, можно просто использовать list comprehension.# In [21]:
list1 = [[1, 2, 3], [4, 5, 6]]
flat_list = [i for j in list1 for i in j]
print(flat_list)
[1, 2, 3, 4, 5, 6]
yield элементов из вложенного списка, а затем преобразовать генератор в список.# In [22]:
def flatten_generator(nested_list):
for sublist in nested_list:
for item in sublist:
yield item
list1 = [[1, 2, 3], [4, 5, 6]]
flat_list = list(flatten_generator(list1))
flat_list
Out[22]: [1, 2, 3, 4, 5, 6]
Шпаргалка по библиотеке Pandas
👉 @PythonPortal
Алгоритмы оптимизации от MIT:
https://drive.google.com/file/d/1Rx7MAekKZbyNVc5B2MNfR0HXXIEJCksp/view
👉 @PythonPortal
Исследователи из Berkeley 8 месяцев работали внутри техкомпании и наблюдали, как сотрудники используют ИИ.
Обещание было простым: ИИ сэкономит вам время. Делайте меньше. Работайте лучше.
На практике вышло наоборот.
Сотрудники не использовали ИИ, чтобы раньше заканчивать работу и идти домой. Они использовали его, чтобы брать на себя больше. Больше задач. Больше проектов. Больше часов работы. Никто их к этому не принуждал. Они сделали это сами.
Исследователи два дня в неделю находились внутри компании на протяжении 8 месяцев. Они наблюдали за 200 сотрудниками в реальном времени. Отслеживали рабочие каналы. Провели более 40 интервью с людьми из engineering, product, design и operations.
Вот что они выяснили. ИИ делал все быстрее на ощущениях, поэтому люди заполняли им каждую свободную паузу. Они отправляли промпты во время обеда. Перед встречами. Поздно ночью. Естественные точки остановки в рабочем дне исчезли. Люди одновременно запускали несколько ИИ-агентов в фоне, пока писали код, готовили документы и сидели на встречах.
Это ощущалось как движение вперед. Это ощущалось как продуктивность. Но если посмотреть на ситуацию со стороны, сами сотрудники описывали свое состояние как перегруженность, постоянную занятость и полную неспособность отключиться от работы.
83% сказали, что ИИ увеличил их рабочую нагрузку. Не снизил. Увеличил.
62% сотрудников уровня associate и 61% сотрудников junior-уровня сообщили о выгорании. Среди руководителей такой же уровень нагрузки ощущали только 38%. Удар приняли на себя те, кто делает реальную работу, в то время как руководство праздновало рост показателей продуктивности.
А потом проявилась ловушка, которую никто не заметил сразу. Когда один человек использует ИИ, чтобы тянуть на себе больше работы, всем остальным начинает казаться, что они отстают. В итоге ускоряется вся команда. Никто официально не повышает ожидания. Но новый темп незаметно становится нормой. То, что ИИ сделал возможным, превращается в то, что от тебя теперь ждут.
Исследователи дали этому название: workload creep.
Сначала это выглядит как рост продуктивности. Потом становится новой базовой нормой. А затем превращается в выгорание.
ИИ должен был вернуть вам время. Вместо этого он забирает его еще больше. И самое неприятное тут вот что: вы делаете это с собой сами. Добровольно. 😢
👉 @PythonPortal
Не используйте ELSE 0 вместе с COUNT и CASE
Использование ELSE 0 - очень частая ошибка у новичков, когда они комбинируют функцию COUNT с выражением CASE. Обычно это происходит из-за непонимания того, как именно COUNT работает при применении к столбцу.
Когда используется COUNT(column), функция считает все значения, которые не равны NULL, включая нули. Это значит, что если в выражении CASE указан ELSE 0, каждая строка, не попавшая под условие, превращается в значение 0. В результате такие строки тоже попадают в подсчёт.
Вот наивный пример:
sql id="g4suvd"
SELECT
Department,
COUNT(CASE
WHEN Status = 'Active' THEN EmployeeID
ELSE 0
END) AS ActiveEmployees
FROM Employees
GROUP BY Department;
0, а это валидное значение, поэтому оно тоже учитывается в COUNT. Из-за этого результат может получиться вводящим в заблуждение.ELSE. Когда ветка ELSE опущена, выражение CASE возвращает NULL для строк, которые не соответствуют условию. А так как COUNT() игнорирует NULL, будут посчитаны только строки, которые действительно удовлетворяют условию. Вот правильный вариант:sql id="vxa5np"
SELECT
Department,
COUNT(CASE
WHEN Status = 'Active' THEN EmployeeID
END) AS ActiveEmployees
FROM Employees
GROUP BY Department;
NULL, и COUNT() естественным образом исключает их из подсчёта. В итоге запрос получается чище, а подсчёт корректно отражает только те значения, которые реально соответствуют условию.
Оказалось, что история с покупкой доступа к якобы топовым моделям, а по факту к подменённым, наконец получила подтверждение в статье.
Исследователи провели аудит 17 сторонних API для LLM-агентов и выяснили:
• почти 46% endpoint'ов не проходят fingerprint-тесты
• API заявляет, что это GPT-5 или Gemini-2.5, а на бэкенде тихо подставлен GLM-4
• точность на медицинском бенчмарке падает с 83% до 37%
Эти фейковые API уже процитированы в 187 научных статьях, а некоторые связанные с ними проекты набрали почти 60 тысяч звёзд на GitHub.
И главная проблема тут в том, что научные выводы строятся на поддельных моделях.
Статья: https://arxiv.org/abs/2603.01919
👉 @PythonPortal
Немного базы Python. # 12 - Startswith и Endswithstartswith() и endswith() это строковые методы, которые возвращают True, если строка начинается или заканчивается указанным значением. Эти методы можно использовать в разных ситуациях, когда нужно проверить префикс или суффикс у строки. Они особенно полезны для фильтрации и задач валидации.
- Использование метода Startswith
Допустим, ты хочешь получить все имена в списке, которые начинаются на a. Вот как можно использовать startswith() для этого:
list1 = ['lemon', 'Orange',
'apple', 'apricot']
new_list = [fruit for fruit in list1 if fruit.startswith('a')]
print(new_list)
['apple', 'apricot']
endswith() можно использовать для валидации ввода пользователя. Например, если нужно проверить, что пользователь ввёл корректный Gmail-адрес, можно убедиться, что ввод заканчивается на gmail.com:user_input = input("Введите email-адрес: ")
if user_input.endswith("@gmail.com"):
print("Валидный email-адрес.")
else:
print("Невалидный email-адрес.")
Agentic RAG для чайников
Модульный agentic RAG, собранный на LangGraph. Разберись с RAG-агентами за считанные минуты.
Этот репозиторий показывает, как собрать agentic RAG на LangGraph с минимумом кода.
Что обещают в README, если коротко:
- иерархическая индексация (parent/child чанки: ищем по мелким, достаём крупные для контекста)
- память диалога
- уточнение запроса (вплоть до паузы и вопроса пользователю)
- оркестрация пайплайна через LangGraph, плюс параллельный map-reduce для сложных запросов
- автоперезапрос, если результатов мало, и компрессия контекста, чтобы не раздувать промпт
https://github.com/GiovanniPasq/agentic-rag-for-dummies
👉 @PythonPortal
Немного базы Python. День 11 - Добавление разделителя тысяч
Если вы работаете с большими числами и хотите добавить разделитель, чтобы их было проще читать, есть несколько способов это сделать. Вот некоторые из них:
▪️Использование функции format
List comprehension проходит по каждому элементу (числу) в my_list. Для каждого числа он форматирует его в строку с разделителями тысяч запятыми, используя строку формата '{:,}'.format(num).
my_list = [10898767, 9876780, 9908763]
new_list = ['{:,}'.format(num) for num in my_list]
print(new_list)
# ['10,898,767', '9,876,780', '9,908,763']
new_list, который содержит отформатированные строки с разделителями запятыми.,) как разделителя мы используем подчёркивание (_).my_list = [10898767, 9876780, 9908763]
new_list = [f"{num:_}" for num in my_list]
print(new_list)
# ['10_898_767', '9_876_780', '9_908_763']
localelocale даёт способ форматировать числа с разделителями тысяч в соответствии с текущими настройками локали. Вы можете выставить нужную локаль и использовать метод locale.format_string(). Вот как это выглядит на практике:import locale
my_list = [10898767, 9876780, 9908763]
formatted_list = []
for num in my_list:
# Set the locale
locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')
formatted_list.append(locale.format_string("%d", num, grouping=True))
print(formatted_list)
my_list через цикл for. Он задаёт нужную локаль 'en_US.UTF-8' с помощью locale.setlocale(locale.LC_ALL, 'en_US.UTF-8'). Это выставляет локаль на США с кодировкой UTF-8, где для тысяч используются запятые. Дальше locale.format_string('%d', num, grouping=True) форматирует число (num) в строку с разделителями тысяч. Спецификатор формата '%d' означает, что число нужно форматировать как целое, а grouping=True указывает, что разделители тысяч должны быть включены.
Советы от реальных экспертов по оптимизации
👉 @PythonPortal
Этот Python-фреймворк может скрейпить ЛЮБОЙ сайт и вытаскивать структурированные данные за считанные минуты.
Называется Scrapy. Он краулит сайты и извлекает структурированные данные целиком с твоей машины.
Никаких счетов за SaaS-скрейпинг. Никаких лимитов облачных API. Никакие данные не уходят за пределы твоей инфраструктуры.
Работает на самом “боевом” краулинг-движке в Python: 59K звёзд и 15+ лет продакшен-использования.
→ Описал spider один раз
→ Получил чистые структурированные данные
→ Масштабируешься до миллионов страниц
→ Экспорт в JSON, CSV, XML в один момент
Всё локально. Ноль зависимости от облака.
Но это не просто скрипт для парсинга.
Это полноценный фреймворк для извлечения данных:
→ Асинхронная архитектура для параллельного краулинга в масштабе
→ Встроенные middleware для прокси, ретраев и rate limiting
→ CSS и XPath селекторы без лишнего бойлерплейта
→ Подключаемые pipelines для чистки, дедупликации и сохранения
→ 54 800+ продакшен-проектов уже завязаны на него
100% open source. Лицензия BSD-3.
Работает на macOS, Windows и Linux уже сейчас.
Хочешь сделать хорошо, сделай сам, вместо облачных сервисов запускаешь всё у себя. 🪖🪖
100% опенсорс
👉 @PythonPortal
Немного базы Python. День 9. Индекс наибольшего числа
Есть несколько способов найти индекс самого большого числа в списках.
▪️Функция max() и метод index()
Можно использовать метод index() вместе с функцией max(), чтобы получить индекс наибольшего числа в списке. В этом примере мы с помощью max() находим самое большое число в списке и передаем его в index() как аргумент. Метод index() вернет индекс первого вхождения наибольшего числа.
In [23]: my_list = [12, 45, 67, 89, 34, 67, 13]
largest_number_index = my_list.index(max(my_list))
largest_number_index
Out[23]: 3
max() и enumerate()max() принимает список и lambda-функцию в качестве аргументов. Мы добавляем enumerate() к списку, чтобы она могла вернуть и число из списка, и его индекс (кортеж). Параметр start в enumerate() задаем так, чтобы нумерация начиналась с позиции 0. lambda-функция используется, чтобы найти максимальное значение по второму элементу каждого кортежа, то есть по значению из my_list.In [24]: my_list = [12, 45, 67, 89, 34, 67, 13]
max_num = max(enumerate(my_list, start=0),
key = lambda x: x[1])
print('Индекс наибольшего числа:',
max_num[0])
Индекс наибольшего числа: 3
enumerate()enumerate(), чтобы найти индекс самого большого числа в списке. Создаем переменную max_value - в ней хранится максимальное значение из списка. Дальше с помощью enumerate() находим индекс(ы), где значение совпадает с этим максимумом.In [25]: my_list = [12, 45, 67, 89, 34, 67, 13]
max_value = max(my_list)
max_indices = [idx for idx, val in enumerate(my_list) if val == max_value]
max_indices
Out[25]: [3]
Ну кто опять накатил питона на принтер ??
👉 @PythonPortal
Немного базы Python. День 7. Подсчет количества вхождений элемента
Если тебе нужно узнать, сколько раз элемент встречается в итерируемой коллекции, можно использовать класс Counter из модуля collections. Counter() вернет словарь с тем, сколько раз каждый элемент встречается в последовательности. Допустим, мы хотим узнать, сколько раз имя Peter встречается в следующем списке. Можно использовать Counter(). См. ниже:
from collections import Counter
list1 = ['John', 'Kelly', 'Peter', 'Moses', 'Peter']
count_peter = Counter(list1).get("Peter")
print(f'The name "Peter" appears in the list '
f'{count_peter} times.')
The name "Peter" appears in the list 2 times.
for. Мы заводим переменную-счетчик и увеличиваем ее на 1 каждый раз, когда находим имя Peter в последовательности. Это наивный способ. См. ниже:list1 = ['John', 'Kelly', 'Peter', 'Moses', 'Peter']
# Create a count variable
count = 0
for name in list1:
if name == 'Peter':
count +=1
print(f'The name "Peter" appears in the list'
f' {count} times.')
The name "Peter" appears in the list 2 times.
count(), который позволяет посчитать количество вхождений конкретного элемента. Мы можем использовать count(), чтобы посчитать, сколько раз Peter встречается в списке.list1 = ['John', 'Kelly', 'Peter', 'Moses', 'Peter']
print(f'The name "Peter" appears in the list '
f'{list1.count("Peter")} times.')
The name "Peter" appears in the list 2 times.