Архив рубрики ~Лента новостей~

Интеграция Langfuse с приложением .NET: пример использования OpenTelemetry

Интеграция Langfuse с приложением .NET: пример использования OpenTelemetry

Несмотря на растущую популярность платформы Langfuse для отладки и контроля LLM ориентированных приложений, на момент написания статьи экосистема .NET остается без официальной поддержки. На момент написания статьи готовые SDK доступны только разработчикам на Python и JavaScript/TypeScript. Однако есть возможность интеграции с помощью стандарта OpenTelemetry. И в данной статье будет приведен один из примеров как это сделать.

Нам понадобится доступ к удаленному или развернутому локально сервису Langfuse. В данном примере будет использован именно локальный вариант, запущенный в Docker с помощью этого файла compose. В результате для правильного функционирования работает целых шесть контейнеров.

Контейнеры Langfuse
Контейнеры Langfuse

Также в примере будет использована локально развернутая модель qwen3:8b с помощью Ollama. Строго говоря, в рамках освещаемой в статье проблемы, доступ к модели не обязателен, т.к. можно ограничиться просто имитацией работы LLM, поэтому именно на её разворачивании останавливаться не буду.

Для примера будет использован шаблон проекта ASP .NET Core Web API со стилем Minimal APIs. Для реализации понадобятся следующие nuget-пакеты:

  • OpenAI — обеспечивает удобный доступ к OpenAI-совместимым REST API.

  • OpenTelemetry.Extensions.Hosting — главный пакет для использования функционала OpenTelemetry.

  • OpenTelemetry.Exporter.OpenTelemetryProtocol — универсальный способ добавления экспорта данных, в том числе трасс.

  • OpenTelemetry.Instrumentation.AspNetCore — инструментация для трасс веб-запросов.

  • OpenTelemetry.Exporter.Console — вывод данных на консоль. Необязателен, но полезен для начальный проверки.

Для последующего удобного добавления экспорта в Langfuse реализован метод расширения с настройками экспорта:

using OpenTelemetry.Trace; using System; using System.Text; namespace LangfuseTracing.Host.Telemetry; public static class LangfuseExporter { public static void AddLangfuseExporter(this TracerProviderBuilder tracerProviderBuilder, LangfuseExporterConfig config) { tracerProviderBuilder .AddOtlpExporter(opt => { opt.Endpoint = CreateUri(config.BaseUrl); opt.Headers = CreateAuthHeader(config.PublicKey, config.SecretKey); opt.Protocol = config.Protocol; opt.TimeoutMilliseconds = (int)config.Timeout.TotalMilliseconds; }); } private static Uri CreateUri(string baseUrl) => new($»{baseUrl}/api/public/otel/v1/traces»); private static string CreateAuthHeader(string publicKey, string secretKey) { var authString = Convert.ToBase64String(Encoding.UTF8.GetBytes($»{publicKey}:{secretKey}»)); return $»Authorization=Basic {authString}»; } }

Добавление в приложение OpenTelemetry-сервисов:

public static IServiceCollection AddOpenTelemetry(this IServiceCollection services, IConfiguration configuration) { var config = configuration.GetConfig<LangfuseExporterConfig>(); services .AddOpenTelemetry() .WithTracing(c => { var resBuilder = ResourceBuilder .CreateDefault() .AddService(ActivityProvider.ServiceName, serviceVersion: «0.0.1»); c.SetResourceBuilder(resBuilder); c.AddSource(ActivityProvider.SourceName); c.AddAspNetCoreInstrumentation(); c.AddConsoleExporter(); c.AddLangfuseExporter(config); }); return services; }

Самая важная строка — это AddSource. В коде может быть сколь угодно много активностей (spans), но если не добавить здесь источник для прослушивания, фреймворк OpenTelemetry не будет собирать и публиковать трассы, соответствующие указанному имени.

Служебный класс с источником активностей:

using System.Diagnostics; namespace LangfuseTracing.Host.Telemetry; public class ActivityProvider { public const string ServiceName = «LangfuseTracingDemo»; public const string SourceName = nameof(LangfuseTracing); public const string InputTagName = «input»; public const string OutputTagName = «output»; public static ActivitySource Tracer { get; set; } = new(SourceName); }

Код сервиса, где происходит работа с LLM и управление пользовательскими трассами:

using LangfuseTracing.Host.Telemetry; using OpenAI.Chat; using System; using System.Threading.Tasks; namespace LangfuseTracing.Host.Services; public class AiService(ChatClient chatClient) { private readonly ChatClient _chatClient = chatClient; public async Task<string> Do(string prompt) { using var activity = ActivityProvider.Tracer.StartActivity(nameof(StubService)); activity?.SetTag(ActivityProvider.InputTagName, prompt); try { var answer = await GetAnswer(prompt); activity?.SetTag(ActivityProvider.OutputTagName, answer); } catch (Exception e) { activity?.SetTag(ActivityProvider.OutputTagName, «no answer»); activity?.AddException(e); } var traceId = activity?.TraceId.ToHexString(); return traceId ?? «no trace»; } private async Task<string> GetAnswer(string prompt) { ChatCompletion completion = await _chatClient.CompleteChatAsync(prompt); var answer = completion.Content[0].Text; return answer; } }

Важный момент: имена тэгов выбраны не случайно, именно по ним будет привязка к соответствующим разделам Input и Output в Langfuse.

Пришло время сделать вызов конечной точки:

curl -X POST http://localhost:5000/api/aido/how%20are%20you

Вызов конечной точки
Вызов конечной точки

Возвращаемое значение — идентификатор трассы (Trace ID). Ниже представлена визуализация трассы в интерфейсе Langfuse.

Интерфейс Langfuse
Интерфейс Langfuse

Полное решение находится на GitHub по ссылке.

P.S. для написания самой статьи ни одна из LLM-моделей не использовалась 🙂

Источник: habr.com

Оцените материал:

Поделиться
Понравилась статья? Расскажите другим
ВКонтакте
Читайте также
Новости робототехники Ветераны Boston Dynamics запускают Dynamic Creatures, чтобы оживить персонажей с помощью робототехники Архив рубрики ~Коротко из Telegram~ MFA не поможет Если вам всегда казалось, что двухфакторная аутентификация… Архив рубрики ~Коротко из Telegram~ Кинопоиск станет основной ТВ-платформой Билайна Пользователи сервиса «попкорн.билайн» получат доступ… Архив рубрики ~Коротко из Telegram~ Еще о новинках в гаджетах В Китае представлен широкий, монолитный… Архив рубрики ~Коротко из Telegram~ 🪐 Anthropic заменяет вызвавшую недовольство политику хранения данных на новую… Архив рубрики ~Коротко из Telegram~ 🚨 Nvidia объявила о приобретении Hugging Face за $12,93 млрд…. Архив рубрики ~Коротко из Telegram~ Эмм а тут челу Astra создала реальный СОНАР📡 на ноуте,… Архив рубрики ~Коротко из Telegram~ Ну и подтвердилось. OpenAI заявляет, что группа ИИ-агентов получила доказательство… Архив рубрики ~Коротко из Telegram~ 🤔 «Не знаю» — самый редкий ответ ИИ Главная проблема… Архив рубрики ~Полезное~ Представляем ChatGPT Images 2.5 | OpenAI Архив рубрики ~Обо всем~ Новая услуга скрининга CRISPR, канналила Calla Lily присоединяется к программе Wellcome Leap, колледж Бейлора создаст центр трансплантации ксеноливеров. Архив рубрики ~Коротко из Telegram~ Xiaomi представила свою широкую раскладушку 18 Fold. ⚪️ внешний дисплей… Архив рубрики ~Коротко из Telegram~ 🙂 Свежий эпизод Practical AI (E370, 3 сентября) — разговор… Архив рубрики ~Коротко из Telegram~ 🌟 Дженсен Хуанг повторяет один тезис на всех крупных площадках:… Новости робототехники Ветераны Boston Dynamics запускают Dynamic Creatures, чтобы оживить персонажей с помощью робототехники Архив рубрики ~Коротко из Telegram~ MFA не поможет Если вам всегда казалось, что двухфакторная аутентификация… Архив рубрики ~Коротко из Telegram~ Кинопоиск станет основной ТВ-платформой Билайна Пользователи сервиса «попкорн.билайн» получат доступ… Архив рубрики ~Коротко из Telegram~ Еще о новинках в гаджетах В Китае представлен широкий, монолитный… Архив рубрики ~Коротко из Telegram~ 🪐 Anthropic заменяет вызвавшую недовольство политику хранения данных на новую… Архив рубрики ~Коротко из Telegram~ 🚨 Nvidia объявила о приобретении Hugging Face за $12,93 млрд…. Архив рубрики ~Коротко из Telegram~ Эмм а тут челу Astra создала реальный СОНАР📡 на ноуте,… Архив рубрики ~Коротко из Telegram~ Ну и подтвердилось. OpenAI заявляет, что группа ИИ-агентов получила доказательство… Архив рубрики ~Коротко из Telegram~ 🤔 «Не знаю» — самый редкий ответ ИИ Главная проблема… Архив рубрики ~Полезное~ Представляем ChatGPT Images 2.5 | OpenAI Архив рубрики ~Обо всем~ Новая услуга скрининга CRISPR, канналила Calla Lily присоединяется к программе Wellcome Leap, колледж Бейлора создаст центр трансплантации ксеноливеров. Архив рубрики ~Коротко из Telegram~ Xiaomi представила свою широкую раскладушку 18 Fold. ⚪️ внешний дисплей… Архив рубрики ~Коротко из Telegram~ 🙂 Свежий эпизод Practical AI (E370, 3 сентября) — разговор… Архив рубрики ~Коротко из Telegram~ 🌟 Дженсен Хуанг повторяет один тезис на всех крупных площадках:…