Так как в посгресе лежат уже просто векторы определённой размерности, то, как мне кажется, никто не помешает в них добавить ещё пару измерений. Например, если мы ищем похожие товары в интернет-магазине, то, наверно, можно попробовать добавить в вектора такие числа как "длина", "ширина", "цвет", и т. д.
Просто добавить числа не получится, их тоже надо как-то кодировать. Например, нужно понимать должны ли мы учитывать близость чисел друг к другу. Когда мы говорим о длине или ширине, то логично считать 99 более близким и похожим на 100, чем число 1. Но если это будут, например, номера категорий товара, то близость их номеров скорее всего не будет говорить о схожести.
Ещё при добавлении других признаков надо не забывать приводить фичи к одной размерности. Если у одной фичи диапазон значений от -10000 до 10000, а у другой от 0 до 1, то первая будет сильнее влиять на рассчет расстояния, чем вторая.
Понятно, что зависимость от API чужого сервиса — это плохо, поэтому можно попробовать сделать свою систему для получения embeddings. Я нагуглил пару способов, как это сделать на языке Go, но глубоко в эту сторону не копал.
Есть библиотека libp2p для JS/Go/Rust в которой это уже реализовано, и много чего еще. Поднимается нода на сервере (или несколько) и на каждом клиенте. Соединяются с сервером через tcp/websocket/webtransport и получают адреса уже подключившихся клиентов - с каждым можно открыть webrtc соединение. После этого про сервер можно забыть, адреса новых клиентов будут распространяться через webrtc. Можно строить сеть только для открытого документа, а можно сразу для всех клиентов приложения, а поверх нее еще одну сеть для документа. А сервер можно и в качестве TURN использовать, только там это называется Relay. Самостоятельно это писать можно очень долго.
const auto& data = cache.Get()[some_user];
foo(data);
Кажется что всё ОК, и тесты вам покажут что всё ОК. Однако, гард защищающий содержимое от конкурентных обновлений, будет уничтожен на первой строчке, а значит что data потенциально может обновиться в фоне и ссылка начнёт указывать на невалидные данные или недоступную память. И такую проблему фиг осознаешь!
И проблемы случатся уже в проде! Нет, не случатся! Такой код не скомпилируется, сообщение об ошибке попросит вас сохранить гард на стеке:
const auto snapshot = cache.Get();
const auto& data = snapshot[some_user];
foo(data);
Для предотвращения подобных ситуаций есть класс SharedReadablePtr, многие RCU-подобные классы устроены так же (например rcu::ReadablePtr).
Моя тема. Несколько лет рисовал картинки в Транснефти. У них существует приличный гайд по описанию всего — цвета, расположения, состава, шрифтов, слоёв и т.д. Это дало то, что в любой дочке ТН в любом месте были одинаковые интерфейсы на уровне диспетчерских отделов.
Выше правильно написали, что интерфейсы бывают разными. В один заглядывают только при наличии проблем, а в другой смотрят круглосуточно. Оба должны по-разному реализовываться.
А вообще тема избитая, есть, например, HMI Design Workbook от Siemens, или The High Performance HMI от Rockwell, или можно поучиться вот у этих ребят — hmi-project.com
Я не настоящий сварщик и UX/UI не занимаюсь, но курсы проходил.
Что бы из этого я применил
1. Контраст — в темной теме мелкие буквы на темном фоне трудно читать. Вообще по устройству глаза палочки отвечают за различие светлого и темного, а колбочки за цвета. Общая структура страницы считывается по принципу светлый-темный, а подробности это цвет.
Один из тестов — попробуйте посмотреть страницу в оттенках серого. Все ли там будет читаемо?
2. Про использование множества цветов. Хитрый момент в том, что если мы возьмем модель HSL и возьмем разные цвета по H, то это будут действительно разные цвета и выглядеть будет пёстро. Но если мы рамках одного H меняем S и L, то это будут вариации одного цвета.
От себя рекомендую посмотреть блог Эрика Кеннеди на предмет UX/UI (Erik Kennedy).
Мы понимаем такую потребность, но избегаем обзоров и анализа чужого ПО, это довольно рискованно с точки зрения этики, потому что всех не похвалишь, ровно и честно тогда не получится. Поэтому избегаем. Вот посмотрите обзор на Хабре переводной, там есть неплохие решения. Вот ещё хороший материал. Ну и можно посмотреть в сторону Alloy и им подобных.
Пункт 2 на самом деле тоже "План", но в более глобальном понятии. Для игр это называется "дизайн-документ". В нём, в частности, описываются все механики игры, в том числе и читы. ЗАРАНЕЕ. Если такового нет, происходит всякое, например:
Игра про магов, бьющих монстру и растущих в опыте. Уже есть маги, монстры, заклинания, всё уже работает. Приходит "гениальная идея" и одним из левелапов магу будет даваться призыв монстра на свою сторону из небытия.
Ой, нет, не даётся. Потому что есть команда "маги" и команда "монстры". В коде это разные типы, у них разный набор характеристик, разная обработка событий и действий. Монстр не умеет целиться в монстра, он атакует только магов. Магу можно выдать картинку и хиты монстра, но атаками монстра объект "маг" пользоваться просто не умеет, у него есть заклинания, а если они кончились - оружие. А после боя обработка гибели мага и монстра тоже различается, нельзя дать магу оружие с названием атаки монстра и сказать, "бей, всё ок".
Почему так? Потому что так было задумано изначально. Не просто стороны боя А и Б, а "маги" и "монстры".
Ружьё висело на сцене в самом начале, и вот оно стреляет в ногу владельца.
Попробуй прокачать скилы (и программирование и общение на английском) на codingame.com Там будешь создавать не игры конечно, но ботов для соревнований с другими участниками в рамках игр с разными правилами - а это пригодится потом для создания интересных противников уже в своей собственной игре.
Ну и gamedev.ru для поиска русскоязычных партнёров по разработке.
Согласен с автором в целом (хотя я вроде как миллениал). Думаю даже, что он многие моменты он смягчил, в жизни всё немного жестче, конечно в зависимости от амбиций. К сожалению, современная разработка на аутсорсе по agile заточена как раз на таких курсистов. Да, возможно после курсов кто-то попадёт в крупную компанию, как им обещают, где у ведущих программистов зарплаты 6-значные, где самые современные технологии, где им пообещают карьерный рост. Только вот они сами не ведущие, а начинающие, и обещать не значит жениться. Им просто никто и не даст (никогда) сделать больше, чем требуется в джире - просто фикси чужой код и ни в чём себе не отказывай. Шаг вправо-влево - расстрел, ты всего лишь винтик в системе. Уточню, никто в таких компаниях не заинтересован в развитии твоих навыков специалиста (даже если это декларируется), да им легче взять готового, чем тебя учить. Придётся учиться самостоятельно, много и постоянно... Если это действительно твоё, то ты всё примешь и преодолеешь. Только потом, если разделить свою зарплату на кол-во часов, которое ты тратишь на этот труд (который не легче физического, подтверждаю), то обнаружишь, что получаешь обычную медианную зарплату за свою работу по 10-12 часов в день, а может и меньше.
Кодировка ASCII исторически не имела никакого отношения к появлению 8-битового байта, тем более что она сначала была 6-битной, потом 7-битной и только к 1980-м годам получила 8-битные расширения.
А что касается байта, то его придумали в IBM (где, кстати, пользовались кодировкой EBCDIC), чтобы иметь возможность масштабировать архитектуру. Младшие модели S/360 по сути на микропрограммном уровне были 8-разрядными, ради дешевизны. Они исполняли 8-разрядные микропрограммы, которые уже реализовывали 32-разрядный машинный язык S/360. А старшие модели сразу аппаратно работали с 32 разрядами. Подробно об этих вещах написано в статьях уважаемого @SIISII.
Согласен. Раз уж речь идет про Windows, то можно было бы написать сервер на базе API для драйвера поддержки протокола HTTP в ядре - http.sys. В этом API есть возможность указать, что надо передавать в качестве тела ответа содержимое не буфера из памяти, а данные из файла-источника , указанного через его описатель (handle), в указанном диапазоне байт из него (можно - веесь файл). После этого данные передаются внутри ядра, без переключения в режим пользователя.
Только вот писать такое надо не на ASP.NET Core, хотя он с http.sys работать умеет: в нем слишком много накладных расходов на обработку запроса, причем - хуже оптимизированных, чем для Kestrel: к примеру, если для Kestrel получение контекста обработки (это - внутренняя структура) идет по специальному оптимизированому пути, то для http.sys - нет.
Просто добавить числа не получится, их тоже надо как-то кодировать. Например, нужно понимать должны ли мы учитывать близость чисел друг к другу. Когда мы говорим о длине или ширине, то логично считать 99 более близким и похожим на 100, чем число 1. Но если это будут, например, номера категорий товара, то близость их номеров скорее всего не будет говорить о схожести.
Ещё при добавлении других признаков надо не забывать приводить фичи к одной размерности. Если у одной фичи диапазон значений от -10000 до 10000, а у другой от 0 до 1, то первая будет сильнее влиять на рассчет расстояния, чем вторая.
Как альтернатива, использовать word2vec. Вроде для Go тоже завезли https://pkg.go.dev/code.sajari.com/word2vec
Было бы интересно сравнить результаты pgvector с решениями вроде FAISS и Qdrant. Дают ли они какое-то преимущество или наоброт проигрывают постгре.
Есть библиотека libp2p для JS/Go/Rust в которой это уже реализовано, и много чего еще. Поднимается нода на сервере (или несколько) и на каждом клиенте. Соединяются с сервером через tcp/websocket/webtransport и получают адреса уже подключившихся клиентов - с каждым можно открыть webrtc соединение. После этого про сервер можно забыть, адреса новых клиентов будут распространяться через webrtc. Можно строить сеть только для открытого документа, а можно сразу для всех клиентов приложения, а поверх нее еще одну сеть для документа. А сервер можно и в качестве TURN использовать, только там это называется Relay.
Самостоятельно это писать можно очень долго.
Если и добавлять такое в игнор, то я бы посоветовал
.git/info/exclude
, тогда не придется коммитить это вместе с.gitignore
Иначе каждый разработчик проекта будет коммитить в gitignore свои личные локальные файлы.
0000ee01-0000-1000-8000-00805f9b34fb
могу предположить, что внутри ESP32 . по началу 02 00 04 типовая реализация spp over ble (com)
Вот например код:
Кажется что всё ОК, и тесты вам покажут что всё ОК. Однако, гард защищающий содержимое от конкурентных обновлений, будет уничтожен на первой строчке, а значит что data потенциально может обновиться в фоне и ссылка начнёт указывать на невалидные данные или недоступную память. И такую проблему фиг осознаешь!
И проблемы случатся уже в проде!Нет, не случатся! Такой код не скомпилируется, сообщение об ошибке попросит вас сохранить гард на стеке:Для предотвращения подобных ситуаций есть класс SharedReadablePtr, многие RCU-подобные классы устроены так же (например rcu::ReadablePtr).
Что-то типа такого
Выше правильно написали, что интерфейсы бывают разными. В один заглядывают только при наличии проблем, а в другой смотрят круглосуточно. Оба должны по-разному реализовываться.
А вообще тема избитая, есть, например, HMI Design Workbook от Siemens, или The High Performance HMI от Rockwell, или можно поучиться вот у этих ребят — hmi-project.com
Что бы из этого я применил
1. Контраст — в темной теме мелкие буквы на темном фоне трудно читать. Вообще по устройству глаза палочки отвечают за различие светлого и темного, а колбочки за цвета. Общая структура страницы считывается по принципу светлый-темный, а подробности это цвет.
Один из тестов — попробуйте посмотреть страницу в оттенках серого. Все ли там будет читаемо?
2. Про использование множества цветов. Хитрый момент в том, что если мы возьмем модель HSL и возьмем разные цвета по H, то это будут действительно разные цвета и выглядеть будет пёстро. Но если мы рамках одного H меняем S и L, то это будут вариации одного цвета.
От себя рекомендую посмотреть блог Эрика Кеннеди на предмет UX/UI (Erik Kennedy).
https://www.uber.com/blog/how-we-saved-70k-cores-across-30-mission-critical-services/
Можно сделать проще и более быстродействующий (зависит лишь от компаратора).
Компаратор плюс:
Вариант 1 : счетчик+цап(R-2R).
Вариант 2: диф.цепочка (С+R+диод) +пиковый детектор(диод+С).
На выходе получаем напряжение , пропорционально числу импульсов на выходе компаратора. Напряжение измеряем любым мультиметром.
-----------------------------
Вариант 3 : счетчик+светодиод на выход каждого разряда. Число импульсов получаем в двоичном коде на светодиодах.
Пункт 2 на самом деле тоже "План", но в более глобальном понятии. Для игр это называется "дизайн-документ". В нём, в частности, описываются все механики игры, в том числе и читы. ЗАРАНЕЕ. Если такового нет, происходит всякое, например:
Игра про магов, бьющих монстру и растущих в опыте. Уже есть маги, монстры, заклинания, всё уже работает.
Приходит "гениальная идея" и одним из левелапов магу будет даваться призыв монстра на свою сторону из небытия.
Ой, нет, не даётся. Потому что есть команда "маги" и команда "монстры". В коде это разные типы, у них разный набор характеристик, разная обработка событий и действий. Монстр не умеет целиться в монстра, он атакует только магов. Магу можно выдать картинку и хиты монстра, но атаками монстра объект "маг" пользоваться просто не умеет, у него есть заклинания, а если они кончились - оружие. А после боя обработка гибели мага и монстра тоже различается, нельзя дать магу оружие с названием атаки монстра и сказать, "бей, всё ок".
Почему так? Потому что так было задумано изначально. Не просто стороны боя А и Б, а "маги" и "монстры".
Ружьё висело на сцене в самом начале, и вот оно стреляет в ногу владельца.
Попробуй прокачать скилы (и программирование и общение на английском) на codingame.com
Там будешь создавать не игры конечно, но ботов для соревнований с другими участниками в рамках игр с разными правилами - а это пригодится потом для создания интересных противников уже в своей собственной игре.
Ну и gamedev.ru для поиска русскоязычных партнёров по разработке.
Согласен с автором в целом (хотя я вроде как миллениал). Думаю даже, что он многие моменты он смягчил, в жизни всё немного жестче, конечно в зависимости от амбиций. К сожалению, современная разработка на аутсорсе по agile заточена как раз на таких курсистов. Да, возможно после курсов кто-то попадёт в крупную компанию, как им обещают, где у ведущих программистов зарплаты 6-значные, где самые современные технологии, где им пообещают карьерный рост. Только вот они сами не ведущие, а начинающие, и обещать не значит жениться. Им просто никто и не даст (никогда) сделать больше, чем требуется в джире - просто фикси чужой код и ни в чём себе не отказывай. Шаг вправо-влево - расстрел, ты всего лишь винтик в системе. Уточню, никто в таких компаниях не заинтересован в развитии твоих навыков специалиста (даже если это декларируется), да им легче взять готового, чем тебя учить. Придётся учиться самостоятельно, много и постоянно...
Если это действительно твоё, то ты всё примешь и преодолеешь. Только потом, если разделить свою зарплату на кол-во часов, которое ты тратишь на этот труд (который не легче физического, подтверждаю), то обнаружишь, что получаешь обычную медианную зарплату за свою работу по 10-12 часов в день, а может и меньше.
Вообще то, Ethernet не является сердцем Интернета. Бэкбон сидит на MPLS и SDH поверх DWDM и его модификаций. Любопытно, ATM ещё жив?
Кодировка ASCII исторически не имела никакого отношения к появлению 8-битового байта, тем более что она сначала была 6-битной, потом 7-битной и только к 1980-м годам получила 8-битные расширения.
А что касается байта, то его придумали в IBM (где, кстати, пользовались кодировкой EBCDIC), чтобы иметь возможность масштабировать архитектуру. Младшие модели S/360 по сути на микропрограммном уровне были 8-разрядными, ради дешевизны. Они исполняли 8-разрядные микропрограммы, которые уже реализовывали 32-разрядный машинный язык S/360. А старшие модели сразу аппаратно работали с 32 разрядами. Подробно об этих вещах написано в статьях уважаемого @SIISII.
Согласен. Раз уж речь идет про Windows, то можно было бы написать сервер на базе API для драйвера поддержки протокола HTTP в ядре - http.sys. В этом API есть возможность указать, что надо передавать в качестве тела ответа содержимое не буфера из памяти, а данные из файла-источника , указанного через его описатель (handle), в указанном диапазоне байт из него (можно - веесь файл). После этого данные передаются внутри ядра, без переключения в режим пользователя.
Только вот писать такое надо не на ASP.NET Core, хотя он с http.sys работать умеет: в нем слишком много накладных расходов на обработку запроса, причем - хуже оптимизированных, чем для Kestrel: к примеру, если для Kestrel получение контекста обработки (это - внутренняя структура) идет по специальному оптимизированому пути, то для http.sys - нет.