vllm для automatic function calling (параметр --enable-auto-tool-choice) требует указания --tool-call-parser, но ваш формат из chat_template.jinja не похож ни на один из тех что идёт вместе с vllm https://docs.vllm.ai/en/v0.11.2/features/tool_calling/#automatic-function-calling При всём уважении, но заниматься ручным парсингом под ваш формат tool call или писать плагины к vllm - нет никакого желания, а без automatic function calling модель по сути бесполезна.
Теперь есть. Калькой послужили исходники самого Guid’а, только layout структуры правильный, как и все соответствующие методы. А способ сгенерировать 16 байт и положить в эту структуру, как я и писал выше - дело десятое.
P.S. - за велосипед обидно было. Там реализован весь API от System.Guid, полное покрытие тестами. По производительности оно эквивалентно System.Guid, причём как с точки зрения времени выполнения, так и с точки зрения аллоцируемой памяти. Проект с бенчмарками в том же солюшене, можете сами во всём убедиться.
Вы создали что-то что называется стандартно, но при этом никто кроме вас не сможет получить нужные бинарные данные из строкового представления и наоборот никто кроме вас не сможет сказать как этот бинарный массив выглядит в виде строки.
Я как раз это унифицировал. Подробности можно посмотреть в комментарии соседнего треда с @edo1h
А вероятность того что у двух людей строковое представление бинарных данных не совпадет в экстремальной ситуации стремится к 100% (Мерфи не даст соврать)
Да да, ровно поэтому я эту библиотеку и написал.
Вот ничему людей история не учит. LE и BE. Ну сколько можно по тем же граблям ходить?
var input = new byte[]
{
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
};
var guid = new Guid(input);
byte* guidPtr = (byte*)&guid;
var real = string.Concat(Enumerable.Range(0, 15)
.Select(i => guidPtr[i])
.Select(x => x.ToString("X2")))
.ToUpper();
var bytesStr = string.Concat(guid.ToByteArray().Select(x => x.ToString("X2"))).ToUpper();
var toString = guid.ToString().Replace("-", "").ToUpper();
realформируется путём последовательного чтения байт Guid'а
bytesStr формируется из ToByteArray()
toString формируется из вызова ToString()
подали на вход в виде массива байт00112233445566778899AABBCCDDEEFF и получаем такую картину:
real = 00112233445566778899AABBCCDDEE
bytesStr = 00112233445566778899AABBCCDDEEFF
toString = 33221100554477668899AABBCCDDEEFF
А теперь подадим на вход не массив байт, а строку
var input = "00112233445566778899AABBCCDDEEFF";
var guid = new Guid(input);
byte* guidPtr = (byte*)&guid;
var real = string.Concat(Enumerable.Range(0, 15)
.Select(i => guidPtr[i])
.Select(x => x.ToString("X2")))
.ToUpper();
var bytesStr = string.Concat(guid.ToByteArray().Select(x => x.ToString("X2"))).ToUpper();
var toString = guid.ToString().Replace("-", "").ToUpper();
И теперь уже обратная картина
real = 33221100554477668899AABBCCDDEE
bytesStr = 33221100554477668899AABBCCDDEEFF
toString = 00112233445566778899AABBCCDDEEFF
То есть строковое и бинарное представление различаются. Корни эта проблема берёт из самой структуры System.Guid, реализаций конструкторов, методов парсинга и представления в виде строки. Ровно эту проблему я и решал, чтобы все 3 переменных были равны.
Так то refresh token’ы нельзя выдавать в браузер. В случае использования OpenID Connect была возможность так называемого «silent renew», но судя по блогу разработчиков вебкита, она уже канула в лету (для Safari — в последних Technology Preview, для Chrome — в 2022) https://webkit.org/blog/10218/full-third-party-cookie-blocking-and-more/
В драфтах OAuth 2.1 implicit flow выпилили, остались только только authorization code с pkce для public/confidential клиентов и client credentials flow. Соответственно единственный вариант для больших SPA, которые разрабатываются сейчас, с заделом на долгую и счастливую поддержку, которым от провайдера нужно чуть побольше, чем просто аутентификация — это code + pkce и httponly secure куки, к которым имеет доступ только BFF.
1) Ничего не мешает портировать этот код прямо в домен (в любом случае, вашу сборку либо так же референсить, либо эмбеддить). Код этой сборки очень прост.
2) Там есть склейка через && и || плюс инвертирование через !spec.
Использовал данное решение для динамического построения предикатов в проектах, где использовался ORM. Было очень удобно.
Только обязательно настроить Data Protection API, чтобы выставленные куки шифровались, а так же валидировать подпись JWT токена. В противном случае, я как злоумышленник могу пойти и подредачить значение куки, прописав туда любые клеймы, которые захочу и плакала вся авторизация.
UPD. В Телеграм-канале сбера появился анонс что --tool-call-parser gigachat3 появится в vLLM > 0.12.0
vllm для automatic function calling (параметр
--enable-auto-tool-choice) требует указания--tool-call-parser, но ваш формат изchat_template.jinjaне похож ни на один из тех что идёт вместе с vllm https://docs.vllm.ai/en/v0.11.2/features/tool_calling/#automatic-function-callingПри всём уважении, но заниматься ручным парсингом под ваш формат tool call или писать плагины к vllm - нет никакого желания, а без automatic function calling модель по сути бесполезна.
Теперь есть. Калькой послужили исходники самого Guid’а, только layout структуры правильный, как и все соответствующие методы. А способ сгенерировать 16 байт и положить в эту структуру, как я и писал выше - дело десятое.
P.S. - за велосипед обидно было. Там реализован весь API от System.Guid, полное покрытие тестами. По производительности оно эквивалентно System.Guid, причём как с точки зрения времени выполнения, так и с точки зрения аллоцируемой памяти. Проект с бенчмарками в том же солюшене, можете сами во всём убедиться.
Я как раз это унифицировал. Подробности можно посмотреть в комментарии соседнего треда с @edo1h
Да да, ровно поэтому я эту библиотеку и написал.
Задавался этим вопросом при написании каждой строчки кода. Оно корнями ещё в WinApi вростает.
Вот такой незамысловатый пример
realформируется путём последовательного чтения байт Guid'аbytesStrформируется изToByteArray()toStringформируется из вызоваToString()подали на вход в виде массива байт
00112233445566778899AABBCCDDEEFFи получаем такую картину:real = 00112233445566778899AABBCCDDEEbytesStr = 00112233445566778899AABBCCDDEEFFtoString = 33221100554477668899AABBCCDDEEFFА теперь подадим на вход не массив байт, а строку
И теперь уже обратная картина
real = 33221100554477668899AABBCCDDEEbytesStr = 33221100554477668899AABBCCDDEEFFtoString = 00112233445566778899AABBCCDDEEFFТо есть строковое и бинарное представление различаются. Корни эта проблема берёт из самой структуры System.Guid, реализаций конструкторов, методов парсинга и представления в виде строки. Ровно эту проблему я и решал, чтобы все 3 переменных были равны.
Проблема Guid в том что у него родовая травма в виде различия строкового и бинарных представлений.
Вот тут https://github.com/dodopizza/primitives/blob/main/src/Dodo.Primitives/Uuid.cs есть реализация (за моим авторством), с API которое «идентично натуральному», но при этом содержит прямой порядк байт как в строковом, так и в бинарном представлении. Алгоритмы генерации можно сбоку написать какие угодно.
У PAUSE в зависимости от процессорной архитектуры - разная длина https://habr.com/ru/post/415053/
Так то refresh token’ы нельзя выдавать в браузер. В случае использования OpenID Connect была возможность так называемого «silent renew», но судя по блогу разработчиков вебкита, она уже канула в лету (для Safari — в последних Technology Preview, для Chrome — в 2022) https://webkit.org/blog/10218/full-third-party-cookie-blocking-and-more/
В драфтах OAuth 2.1 implicit flow выпилили, остались только только authorization code с pkce для public/confidential клиентов и client credentials flow. Соответственно единственный вариант для больших SPA, которые разрабатываются сейчас, с заделом на долгую и счастливую поддержку, которым от провайдера нужно чуть побольше, чем просто аутентификация — это code + pkce и httponly secure куки, к которым имеет доступ только BFF.
1) Ничего не мешает портировать этот код прямо в домен (в любом случае, вашу сборку либо так же референсить, либо эмбеддить). Код этой сборки очень прост.
2) Там есть склейка через && и || плюс инвертирование через !spec.
Использовал данное решение для динамического построения предикатов в проектах, где использовался ORM. Было очень удобно.
Только обязательно настроить Data Protection API, чтобы выставленные куки шифровались, а так же валидировать подпись JWT токена. В противном случае, я как злоумышленник могу пойти и подредачить значение куки, прописав туда любые клеймы, которые захочу и плакала вся авторизация.