{"id":479305,"date":"2026-05-11T10:32:26","date_gmt":"2026-05-11T10:32:26","guid":{"rendered":"https:\/\/savepearlharbor.com\/?p=479305"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=479305","title":{"rendered":"\u041e\u0442 LLM \u043a \u0430\u0433\u0435\u043d\u0442\u0443: \u041a\u0430\u043a \u0437\u0430\u0441\u0442\u0430\u0432\u0438\u0442\u044c Go \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u0443\u043c\u0430\u0442\u044c \u0438 \u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c"},"content":{"rendered":"<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<blockquote>\n<p><strong>\u041e\u0442 \u0430\u0432\u0442\u043e\u0440\u0430:<\/strong> \u042d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u0440\u043e\u0434\u0438\u043b\u0430\u0441\u044c \u0438\u0437 \u0436\u0435\u043b\u0430\u043d\u0438\u044f \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0437\u0430 \u043a\u0430\u0434\u0440\u043e\u043c \u043e\u0442\u043b\u0438\u0447\u043d\u043e\u0433\u043e \u0434\u043e\u043a\u043b\u0430\u0434\u0430.<\/p>\n<\/blockquote>\n<h3>1. \u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/h3>\n<h4>1.1. \u0418\u0441\u0442\u043e\u0440\u0438\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/h4>\n<p>\u0412\u0441\u0451 \u043d\u0430\u0447\u0430\u043b\u043e\u0441\u044c \u0441 \u0434\u043e\u043a\u043b\u0430\u0434\u0430 \u0410\u043d\u0442\u043e\u043d\u0430 \u042e\u0440\u0447\u0435\u043d\u043a\u043e <a href=\"https:\/\/golangmeetup2025.dialog.sberbank.ru\/translation\" rel=\"noopener noreferrer nofollow\">\u00ab\u0423\u043b\u0443\u0447\u0448\u0430\u0435\u043c \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u043e \u043e\u0442\u0447\u0451\u0442\u043e\u0432 \u043d\u0430\u0433\u0440\u0443\u0437\u043e\u0447\u043d\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Go, LangChain \u0438 GigaChat\u00bb<\/a>.<\/p>\n<p>\u0414\u043e\u043a\u043b\u0430\u0434 \u043c\u043d\u0435 \u043f\u043e\u043d\u0440\u0430\u0432\u0438\u043b\u0441\u044f: \u0447\u0451\u0442\u043a\u0430\u044f \u043f\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b, \u0433\u0440\u0430\u043c\u043e\u0442\u043d\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u043a \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438, \u043e\u0442\u043b\u0438\u0447\u043d\u0430\u044f \u0438\u0434\u0435\u044f \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c LLM \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0447\u0435\u043b\u043e\u0432\u0435\u043a\u043e\u043f\u043e\u043d\u044f\u0442\u043d\u044b\u0445 \u043e\u0442\u0447\u0451\u0442\u043e\u0432. \u041d\u043e \u043f\u043e\u0441\u043b\u0435 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 \u043e\u0441\u0442\u0430\u043b\u0430\u0441\u044c \u043e\u0434\u043d\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u2014 <strong>\u043a\u043e\u0434 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u0442\u0430\u043a \u0438 \u043d\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u0438<\/strong>.<\/p>\n<p>\u0411\u044b\u043b\u043e \u0441\u043a\u0430\u0437\u0430\u043d\u043e \u043b\u0438\u0448\u044c, \u0447\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u00ab\u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u00bb \u0434\u043b\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f GigaChat \u043a LangChain. \u0417\u0432\u0443\u0447\u0438\u0442 \u043f\u0440\u043e\u0441\u0442\u043e, \u043d\u043e \u043a\u043e\u0433\u0434\u0430 \u0442\u044b \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0448\u044c \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e LangChainGo, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043a \u0441\u043b\u043e\u0432\u0443 \u0435\u0449\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u043f\u043e\u043b\u043e\u0432\u0438\u043d\u0443 \u0438 \u043f\u044b\u0442\u0430\u0435\u0448\u044c\u0441\u044f \u043f\u043e\u043d\u044f\u0442\u044c, \u0441 \u0447\u0435\u0433\u043e \u043d\u0430\u0447\u0430\u0442\u044c \u2014 \u0432\u043e\u0437\u043d\u0438\u043a \u0432\u043e\u043f\u0440\u043e\u0441: \u041a\u0430\u043a\u043e\u0439 \u0438\u043c\u0435\u043d\u043d\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c? \u0414\u0430\u043b\u0435\u0435 \u043f\u043e \u0438\u0437\u0443\u0447\u0435\u043d\u0438\u044e \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438  \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u0438 \u0438 \u0434\u0440\u0443\u0433\u0438\u0435:<\/p>\n<ul>\n<li>\n<p>\u0427\u0442\u043e \u0442\u0430\u043a\u043e\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0432 LLM \u0438 \u043a\u0430\u043a \u0438\u0445 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c?<\/p>\n<\/li>\n<li>\n<p>\u041a\u0430\u043a \u0441\u0432\u044f\u0437\u0430\u0442\u044c \u044d\u0442\u043e \u0432\u0441\u0451 \u0441 \u0446\u0435\u043f\u043e\u0447\u043a\u0430\u043c\u0438 (chains) \u0438 \u0437\u0430\u0447\u0435\u043c \u043e\u043d\u0438 \u0432\u043e\u043e\u0431\u0449\u0435 \u043d\u0443\u0436\u043d\u044b?<\/p>\n<\/li>\n<li>\n<p>\u0427\u0442\u043e \u0442\u0430\u043a\u043e\u0435 \u0448\u0430\u0431\u043b\u043e\u043d \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0438 \u043d\u0443\u0436\u043d\u043e \u043b\u0438 \u043c\u043d\u0435 \u0438\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f?<\/p>\n<\/li>\n<\/ul>\n<p>\u0422\u0430\u043a \u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f \u044d\u0442\u043e\u0442 pet-\u043f\u0440\u043e\u0435\u043a\u0442. \u042f \u0440\u0435\u0448\u0438\u043b <strong>\u0441\u0430\u043c \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f \u0438 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0447\u0438\u0439 \u043f\u0440\u0438\u043c\u0435\u0440<\/strong>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0442\u0440\u043e\u0433\u0430\u0442\u044c, \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0438 \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u0442\u044c.<\/p>\n<h4>1.2. \u0426\u0435\u043b\u044c \u0441\u0442\u0430\u0442\u044c\u0438<\/h4>\n<p>\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0447\u0438\u0439 \u043a\u043e\u0434 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 GigaChat \u0441 LangChainGo \u043d\u0430 Go. \u0412 \u043d\u0451\u043c \u044f \u0445\u043e\u0447\u0443 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0443\u043a\u0430\u0437\u0430\u043d\u043e \u0432 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u0445 \u043a\u0430\u043a \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438, \u0442\u0430\u043a \u0438 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 GigaChat, \u0430 \u0438\u043c\u0435\u043d\u043d\u043e \u0441\u0435\u0440\u0432\u0438\u0441 \u043f\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044e \u043f\u043e\u0433\u043e\u0434\u044b, \u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0437\u0430\u043f\u0440\u043e\u0441 \u043a \u043c\u043e\u0434\u0435\u043b\u0438, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043e\u0442\u0434\u0430\u0441\u0442 \u043c\u043d\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0433\u0430\u043b\u043b\u044e\u0446\u0438\u043d\u0430\u0446\u0438\u0438, \u0430 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0438 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435. \u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0430\u0433\u0435\u043d\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0438\u0437 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0433\u043e\u0440\u043e\u0434 \u0438 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0434\u043d\u0435\u0439 \u0434\u043b\u044f \u043f\u0440\u043e\u0433\u043d\u043e\u0437\u0430, \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c  \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u043e\u0433\u043d\u043e\u0437 \u043f\u043e\u0433\u043e\u0434\u044b \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e mcp-\u0441\u0435\u0440\u0432\u0435\u0440\u0430 ,\u0430 \u0437\u0430\u0442\u0435\u043c \u0443\u0436\u0435 \u0438\u043c\u0435\u044f \u0432\u0441\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0433\u043d\u043e\u0437 \u0438 \u0434\u0430\u0432\u0430\u0442\u044c \u0441\u043e\u0432\u0435\u0442 \u043f\u043e \u043e\u0434\u0435\u0436\u0434\u0435, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043e\u0434\u0435\u0442\u044c \u043d\u0430 \u0443\u043b\u0438\u0446\u0443.<\/p>\n<h3>2. \u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430: \u0447\u0442\u043e \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f<\/h3>\n<h4>2.1. \u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438<\/h4>\n<p>\u0414\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0430\u0433\u0435\u043d\u0442\u0430 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 <a href=\"https:\/\/github.com\/tmc\/langchaingo\" rel=\"noopener noreferrer nofollow\">github.com\/tmc\/langchaingo<\/a>, \u0435\u0449\u0451 \u0432 \u0440\u0430\u0431\u043e\u0442\u0435 \u0430\u0433\u0435\u043d\u0442\u0430 \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f:<\/p>\n<ol>\n<li>\n<p>mcp \u0441\u0435\u0440\u0432\u0435\u0440 \u043f\u043e\u0433\u043e\u0434\u044b<\/p>\n<\/li>\n<li>\n<p>\u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0434\u043b\u044f \u0435\u0433\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f <a href=\"https:\/\/github.com\/modelcontextprotocol\/go-sdk\/mcp\" rel=\"noopener noreferrer nofollow\">github.com\/modelcontextprotocol\/go-sdk\/mcp<\/a><\/p>\n<\/li>\n<li>\n<p>GigaChat &#8212; \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0441\u0430\u043c\u0430 \u043c\u043e\u0434\u0435\u043b\u044c<\/p>\n<\/li>\n<li>\n<p>Node.js &#8212; \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b mcp \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043f\u043e\u0433\u043e\u0434\u044b.<\/p>\n<\/li>\n<\/ol>\n<h4>2.2. \u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u0432 Sber Developers<\/h4>\n<p>\u0414\u043b\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a GigaChat API \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0430\u043a\u043a\u0430\u0443\u043d\u0442 \u0432 Sber Developers \u0438 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0442\u0430\u043c \u0441\u0432\u043e\u0439 \u043f\u0440\u043e\u0435\u043a\u0442.<\/p>\n<p><strong>\u0428\u0430\u0433 1:<\/strong> <\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/a8\/59\/f0\/a859f0f5f0d2b0370c5a0d6511db6064.png\" alt=\"\u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043d\u0430 developers.sber.ru, \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c\u0441\u044f \u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0443\u0435\u043c\u0441\u044f.\" sizes=\"(max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/webt\/a8\/59\/f0\/a859f0f5f0d2b0370c5a0d6511db6064.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/webt\/a8\/59\/f0\/a859f0f5f0d2b0370c5a0d6511db6064.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043d\u0430 developers.sber.ru, \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c\u0441\u044f \u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0443\u0435\u043c\u0441\u044f.<\/figcaption><\/div>\n<\/figure>\n<p><strong>\u0428\u0430\u0433 2:<\/strong><\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/69\/21\/31\/69213113408fb7e0fde012e865c39f32.png\" alt=\"\u0412\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442.\" sizes=\"(max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/webt\/69\/21\/31\/69213113408fb7e0fde012e865c39f32.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/webt\/69\/21\/31\/69213113408fb7e0fde012e865c39f32.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0412\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442.<\/figcaption><\/div>\n<\/figure>\n<p><strong>\u0428\u0430\u0433 3:<\/strong><\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/c8\/1f\/4e\/c81f4ea6e5e0aa2b9cdbd16913e5c44b.png\" alt=\"\u0412\u044b\u0431\u0438\u0440\u0430\u0435\u043c AI-\u043c\u043e\u0434\u0435\u043b\u0438 -&gt; GigaChat API\" sizes=\"(max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/webt\/c8\/1f\/4e\/c81f4ea6e5e0aa2b9cdbd16913e5c44b.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/webt\/c8\/1f\/4e\/c81f4ea6e5e0aa2b9cdbd16913e5c44b.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0412\u044b\u0431\u0438\u0440\u0430\u0435\u043c AI-\u043c\u043e\u0434\u0435\u043b\u0438 -&gt; GigaChat API<\/figcaption><\/div>\n<\/figure>\n<p><strong>\u0428\u0430\u0433 4:<\/strong><\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/53\/b1\/1c\/53b11cdc5f0ee8221baa1c4adf45501c.png\" alt=\"\u0417\u0430\u0445\u043e\u0434\u0438\u043c \u0432 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442\" sizes=\"(max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/webt\/53\/b1\/1c\/53b11cdc5f0ee8221baa1c4adf45501c.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/webt\/53\/b1\/1c\/53b11cdc5f0ee8221baa1c4adf45501c.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0417\u0430\u0445\u043e\u0434\u0438\u043c \u0432 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442<\/figcaption><\/div>\n<\/figure>\n<p><strong>\u0428\u0430\u0433 5:<\/strong><\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/c0\/94\/c8\/c094c88fd27487e1d2cedf0cac762c2c.png\" alt=\"\u0412\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c API \u0438 \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043d\u043e\u0432\u044b\u0439 \u043a\u043b\u044e\u0447\" sizes=\"(max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/webt\/c0\/94\/c8\/c094c88fd27487e1d2cedf0cac762c2c.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/webt\/c0\/94\/c8\/c094c88fd27487e1d2cedf0cac762c2c.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0412\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c API \u0438 \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043d\u043e\u0432\u044b\u0439 \u043a\u043b\u044e\u0447<\/figcaption><\/div>\n<\/figure>\n<h4>2.3. \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0438 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/h4>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442 weather-agent<\/p>\n<pre><code>go mod init weather-agent<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:87px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>C\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430:<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/d1\/24\/5a\/d1245a98ab1da61fd96501e892212e8f.png\" alt=\"\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\" sizes=\"(max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/webt\/d1\/24\/5a\/d1245a98ab1da61fd96501e892212e8f.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/webt\/d1\/24\/5a\/d1245a98ab1da61fd96501e892212e8f.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/figcaption><\/div>\n<\/figure>\n<h3>3. \u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/h3>\n<h4>3.1. \u041e\u0431\u0449\u0430\u044f \u0441\u0445\u0435\u043c\u0430<\/h4>\n<p>\u041d\u0435\u043c\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0432\u0448\u0438\u0441\u044c \u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 langchaingo \u044f \u0443\u0437\u043d\u0430\u043b, \u0447\u0442\u043e \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u043b\u044e\u0431\u043e\u0439 \u0430\u0433\u0435\u043d\u0442 \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432:<\/p>\n<ul>\n<li>\n<p>\u041c\u043e\u0434\u0435\u043b\u044c, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u043e\u0441\u043d\u043e\u0432\u043e\u0439 \u0430\u0433\u0435\u043d\u0442\u0430 (Model)<\/p>\n<\/li>\n<li>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u0438 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u043d\u0430 \u0443\u043c\u0435\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c (Tools)<\/p>\n<\/li>\n<li>\n<p>\u041f\u0430\u043c\u044f\u0442\u044c \u043c\u043e\u0434\u0435\u043b\u0438 (Brain)<\/p>\n<\/li>\n<li>\n<p>\u0426\u0435\u043f\u043e\u0447\u043a\u0438 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u0430\u0433\u0435\u043d\u0442\u0430 (Chain)<\/p>\n<\/li>\n<\/ul>\n<p>\u042d\u0442\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435  \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0430\u0433\u0435\u043d\u0442\u0430 \u0438 \u0438\u0445 \u043c\u043e\u0436\u043d\u043e \u043a\u043e\u043c\u0431\u0438\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c, \u0430 \u0447\u0442\u043e\u0431\u044b \u0430\u0433\u0435\u043d\u0442 \u0431\u044b\u043b \u0431\u043e\u043b\u0435\u0435 \u0434\u0435\u0442\u0435\u0440\u043c\u0438\u043d\u0438\u0440\u043e\u0432\u0430\u043d, \u043c\u044b \u043a\u0430\u043a \u0438 \u0432 \u043e\u0431\u044b\u043a\u043d\u043e\u0432\u0435\u043d\u043d\u043e\u0439 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0435 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0435\u043c\u0443 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0446\u0435\u043f\u043e\u0447\u043a\u0430. \u0421\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044f \u044d\u0442\u0438 \u0446\u0435\u043f\u043e\u0447\u043a\u0438 \u043c\u044b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0440\u0430\u0431\u043e\u0442\u044b \u0430\u0433\u0435\u043d\u0442\u0430, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u0435\u043c \u0434\u0435\u043b\u0430\u0442\u044c \u0432\u043e\u0437\u0432\u0440\u0430\u0442 \u043a \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0439 \u043d\u0430\u043c \u0447\u0430\u0441\u0442\u0438 \u0446\u0435\u043f\u043e\u0447\u043a\u0438 \u043f\u0440\u0438 \u0441\u0431\u043e\u0435, \u0438\u043b\u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u0435\u043d\u0438\u044e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0435\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430. \u042f \u0440\u0435\u0448\u0438\u043b \u043d\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u043f\u0430\u043c\u044f\u0442\u044c \u0432 \u0441\u0432\u043e\u0435\u0433\u043e \u0430\u0433\u0435\u043d\u0442\u0430, \u0442\u0430\u043a \u043a\u0430\u043a \u044d\u0442\u043e \u043d\u0435 \u043e\u0441\u043e\u0431\u043e \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u043f\u0440\u043e\u0433\u043d\u043e\u0437\u0430 \u043f\u043e\u0433\u043e\u0434\u044b, \u043d\u043e \u043f\u0440\u0438 \u0436\u0435\u043b\u0430\u043d\u0438\u0438 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u043f\u0430\u043c\u044f\u0442\u0438 \u0435\u0441\u043b\u0438 \u0432\u0430\u043c \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/3f\/06\/46\/3f0646aee44d03446f71c8e2c3e29991.png\" alt=\"\u0421\u0445\u0435\u043c\u0430 \u0440\u0430\u0431\u043e\u0442\u044b \u0430\u0433\u0435\u043d\u0442\u0430\" sizes=\"(max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/webt\/3f\/06\/46\/3f0646aee44d03446f71c8e2c3e29991.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/webt\/3f\/06\/46\/3f0646aee44d03446f71c8e2c3e29991.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0421\u0445\u0435\u043c\u0430 \u0440\u0430\u0431\u043e\u0442\u044b \u0430\u0433\u0435\u043d\u0442\u0430<\/figcaption><\/div>\n<\/figure>\n<h4>3.2. \u041a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b<\/h4>\n<p><strong>GigaChatLLM<\/strong> &#8212; \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 <code>llms.Model<\/code> \u0434\u043b\u044f GigaChat, <strong>Agent<\/strong> &#8212; \u041a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u043e\u0440 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0438 \u0438\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c \u0446\u0435\u043f\u043e\u0447\u0435\u043a (WeatherAgent), <strong>Chains<\/strong> &#8212; \u0426\u0435\u043f\u043e\u0447\u043a\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432, <strong>Tools<\/strong> &#8212; \u0412\u043d\u0435\u0448\u043d\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 (weather \u0447\u0435\u0440\u0435\u0437 MCP), <strong>MCP Client<\/strong> &#8212; \u041a\u043b\u0438\u0435\u043d\u0442 \u0434\u043b\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043a weather-\u0441\u0435\u0440\u0432\u0435\u0440\u0443<\/p>\n<h3>4. \u041f\u043e\u0442\u043e\u043a \u0434\u0430\u043d\u043d\u044b\u0445: \u043e\u0442 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0434\u043e \u043e\u0442\u0432\u0435\u0442\u0430<\/h3>\n<p>\u0420\u0430\u0437\u0431\u0435\u0440\u0451\u043c \u043f\u043e\u043b\u043d\u044b\u0439 \u043f\u0443\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435: <strong>\u00ab\u041a\u0430\u043a\u0430\u044f \u043f\u043e\u0433\u043e\u0434\u0430 \u0432 \u041c\u043e\u0441\u043a\u0432\u0435 \u043d\u0430 3 \u0434\u043d\u044f?\u00bb<\/strong><\/p>\n<h4>4.1. \u0428\u0430\u0433 1: HTTP-\u0437\u0430\u043f\u0440\u043e\u0441 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f<\/h4>\n<pre><code class=\"bash\">POST http:\/\/localhost:8080\/api\/weather\/processContent-Type: application\/json{  \"prompt\": \"\u041a\u0430\u043a\u0430\u044f \u043f\u043e\u0433\u043e\u0434\u0430 \u0432 \u041d\u043e\u0432\u043e\u0441\u0438\u0431\u0438\u0440\u0441\u043a\u0435 \u043d\u0430 7 \u0434\u043d\u0435\u0439?\"}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h4>4.2. \u0428\u0430\u0433 2: \u041a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 (controller.go)<\/h4>\n<p><strong>\u0424\u0430\u0439\u043b:<\/strong> <code>controller.go<\/code><\/p>\n<pre><code class=\"go\">const (weatherProcessRoute = \"\/weather\/process\" )\/\/ AgentRequest \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441 \u043a \u0430\u0433\u0435\u043d\u0442\u0443 \u0441 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u043c \u043f\u0440\u043e\u043c\u043f\u0442\u043e\u043c.type AgentRequest struct {Prompt string `json:\"prompt\"` \/\/ \u0422\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f}\/\/ llmRoutes \u0445\u0440\u0430\u043d\u0438\u0442 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043a LLM.type llmRoutes struct {l     *slog.Logger        \/\/ l \u2014 \u043b\u043e\u0433\u0433\u0435\u0440 \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0439agent *agent.WeatherAgent \/\/ agent \u2014 \u0430\u0433\u0435\u043d\u0442 \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043e \u043f\u043e\u0433\u043e\u0434\u0435}\/\/ newLLMRoutes \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 \u0432\u0441\u0435 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u044b \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 LLM.func newLLMRoutes(api fiber.Router, l *slog.Logger, agent *agent.WeatherAgent) {\/\/ \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0441 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044f\u043c\u0438lr := llmRoutes{l, agent}\/\/ \u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043aapi.Post(weatherProcessRoute, lr.ProcessWeather)}\/\/ ProcessWeather \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441 \u043e \u043f\u0440\u043e\u0433\u043d\u043e\u0437\u0435 \u043f\u043e\u0433\u043e\u0434\u044b.func (lr *llmRoutes) ProcessWeather(c fiber.Ctx) error {\/\/ \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0441 \u0442\u0430\u0439\u043c\u0430\u0443\u0442\u043e\u043c 60 \u0441\u0435\u043a\u0443\u043d\u0434 \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0433\u043d\u043e\u0437\u0430ctx, cancel := context.WithTimeout(c.Context(), 60*time.Second)defer cancel()\/\/ \u041f\u0430\u0440\u0441\u0438\u043c JSON \u0438\u0437 \u0442\u0435\u043b\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0432 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 AgentRequestvar req AgentRequestraw := c.BodyRaw()if err := json.Unmarshal(raw, &amp;req); err != nil {\/\/ \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c HTTP 400 \u043f\u0440\u0438 \u043d\u0435\u0432\u0430\u043b\u0438\u0434\u043d\u043e\u043c JSONreturn c.Status(http.StatusBadRequest).JSON(fiber.Map{\"success\": false,\"error\":   \"\u041d\u0435\u0432\u0430\u043b\u0438\u0434\u043d\u044b\u0439 JSON\",})}\/\/ \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e \u043f\u043e\u043b\u0435 prompt \u043d\u0435 \u043f\u0443\u0441\u0442\u043e\u0435if req.Prompt == \"\" {return c.Status(http.StatusBadRequest).JSON(fiber.Map{\"success\": false,\"error\":   \"\u041f\u043e\u043b\u0435 'prompt' \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e\",})}\/\/ \u041b\u043e\u0433\u0438\u0440\u0443\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u043e \u043f\u043e\u0433\u043e\u0434\u0435 \u0441 \u0434\u043b\u0438\u043d\u043e\u0439 \u043f\u0440\u043e\u043c\u043f\u0442\u0430lr.l.Info(\"[ProcessWeather] Processing weather request\", \"prompt_length\", len(req.Prompt))\/\/ \u041f\u0435\u0440\u0435\u0434\u0430\u0451\u043c \u0437\u0430\u043f\u0440\u043e\u0441 \u0430\u0433\u0435\u043d\u0442\u0443 \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438response, err := lr.agent.ProcessWeather(ctx, req.Prompt)if err != nil {\/\/ \u041b\u043e\u0433\u0438\u0440\u0443\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0443 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438lr.l.Error(\"[ProcessWeather] Agent execution failed\", \"error\", err)\/\/ \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c HTTP 500 \u0441 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0438return c.Status(http.StatusInternalServerError).JSON(fiber.Map{\"success\": false,\"error\":   \"\u041e\u0448\u0438\u0431\u043a\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0430: \" + err.Error(),})}\/\/ \u041b\u043e\u0433\u0438\u0440\u0443\u0435\u043c \u0443\u0441\u043f\u0435\u0448\u043d\u0443\u044e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0441 \u0434\u043b\u0438\u043d\u043e\u0439 \u043e\u0442\u0432\u0435\u0442\u0430lr.l.Info(\"[ProcessWeather] Success\", \"response_length\", len(response))\/\/ \u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u043e\u0442\u0432\u0435\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0443return c.Status(http.StatusOK).JSON(fiber.Map{\"success\":  true,\"response\": response,\"message\":  \"\u0417\u0430\u043f\u0440\u043e\u0441 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d\",})}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h4>4.3. \u0428\u0430\u0433 3: \u0410\u0433\u0435\u043d\u0442 (agent\/weather_agent.go)<\/h4>\n<p><strong>\u0424\u0430\u0439\u043b:<\/strong> <code>agent\/weather_agent.go<\/code><\/p>\n<pre><code class=\"go\">\/\/ \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0434\u043b\u044f \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.type Logger interface {Debug(msg string, args ...any)Info(msg string, args ...any)Warn(msg string, args ...any)Error(msg string, args ...any)}\/\/ \u043e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0430\u0433\u0435\u043d\u0442\u0430 \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043e \u043f\u043e\u0433\u043e\u0434\u0435.type WeatherAgent struct {llm    llms.Model                   \/\/ \u044f\u0437\u044b\u043a\u043e\u0432\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044ctool   *weather.WeatherForecastTool \/\/ \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0430\u0433\u0435\u043d\u0442\u0430logger Logger                       \/\/ \u043b\u043e\u0433\u0433\u0435\u0440}\/\/ NewWeatherAgent \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442 \u043d\u043e\u0432\u044b\u0439 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 WeatherAgent.func NewWeatherAgent(llm llms.Model, l Logger) *WeatherAgent {l.Info(\"[WeatherAgent] Agent initialized\")weatherTool := weather.NewWeatherForecastTool()return &amp;WeatherAgent{llm:    llm,tool:   weatherTool,logger: l,}}\/\/ ProcessWeather \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441 \u043e \u043f\u0440\u043e\u0433\u043d\u043e\u0437\u0435 \u043f\u043e\u0433\u043e\u0434\u044b.func (wa *WeatherAgent) ProcessWeather(ctx context.Context, input string) (string, error) {wa.logger.Info(\"[WeatherAgent] Starting weather processing\", \"input_preview\", input)\/\/ \u043e\u0442\u0434\u0430\u0435\u043c \u043d\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043f\u0440\u043e\u043c\u0442\u0430 \u0446\u0435\u043f\u043e\u0447\u043a\u043e\u0439 \u0430\u0433\u0435\u043d\u0442\u0430result, err := weather.HandleWeatherRequest(ctx, wa.llm, wa.tool, wa.logger, input)if err != nil {wa.logger.Error(\"[WeatherAgent] Weather processing failed\", \"error\", err)return \"\", err}wa.logger.Info(\"[WeatherAgent] Weather processing completed successfully\")return result, nil}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h4>4.4. \u0428\u0430\u0433 4: \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043f\u043e\u0433\u043e\u0434\u044b (weather\/handler.go)<\/h4>\n<p><strong>\u0424\u0430\u0439\u043b:<\/strong> <code>weather\/handler.go<\/code><\/p>\n<pre><code class=\"go\">func HandleWeatherRequest(ctx context.Context, llm llms.Model, tool *WeatherForecastTool, l Logger, userInput string) (string, error) {\/\/ \u041b\u043e\u0433\u0438\u0440\u0443\u0435\u043c \u043d\u0430\u0447\u0430\u043b\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043f\u043e\u0433\u043e\u0434\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430l.Info(\"[WeatherHandler] Starting weather forecast chain\", \"input\", userInput)\/\/ \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u0446\u0435\u043f\u043e\u0447\u043a\u0438 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u044d\u0442\u0430\u043f\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438\/\/ createExtractArgsChain \u2014 \u0438\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u0442 \u0433\u043e\u0440\u043e\u0434 \u0438 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0434\u043d\u0435\u0439 \u0438\u0437 \u0437\u0430\u043f\u0440\u043e\u0441\u0430extractChain := createExtractArgsChain(llm, l)\/\/ createParseArgsChain \u2014 \u043f\u0430\u0440\u0441\u0438\u0442 JSON \u0441 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u0432 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443parseArgsChain := createParseArgsChain(l)\/\/ createWeatherToolChain \u2014 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u043f\u043e\u0433\u043e\u0434\u044b \u0441 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u043c\u0438 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430\u043c\u0438weatherToolChain := createWeatherToolChain(tool, l)\/\/ createFinalResponseChain \u2014 \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u0443\u0435\u0442 \u0444\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u043e\u0442\u0432\u0435\u0442 \u0441 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u044f\u043c\u0438finalResponseChain := createFinalResponseChain(llm)\/\/ \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u0446\u0435\u043f\u043e\u0447\u043a\u0443 \u0438\u0437 \u0432\u0441\u0435\u0445 \u044d\u0442\u0430\u043f\u043e\u0432accumulatingChain := NewAccumulatingSequentialChain([]chains.Chain{extractChain,parseArgsChain,weatherToolChain,finalResponseChain,})l.Info(\"[WeatherHandler] AccumulatingSequentialChain created, executing...\")\/\/ \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0446\u0435\u043f\u043e\u0447\u043a\u0443 \u0441 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u043cresult, err := accumulatingChain.Call(ctx, map[string]any{\"userInput\": userInput,})if err != nil {\/\/ \u041b\u043e\u0433\u0438\u0440\u0443\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0443 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0446\u0435\u043f\u043e\u0447\u043a\u0438l.Error(\"[WeatherHandler] AccumulatingSequentialChain execution failed\", \"error\", err)return \"\", err}\/\/ \u0418\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u043c \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0438\u0437 \u0432\u044b\u0445\u043e\u0434\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445finalOutput, ok := result[\"text\"].(string)if !ok {\/\/ \u041b\u043e\u0433\u0438\u0440\u0443\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0443 \u0442\u0438\u043f\u0430 \u0434\u0430\u043d\u043d\u044b\u0445l.Error(\"[WeatherHandler] Invalid output type from AccumulatingSequentialChain\")return \"\", fmt.Errorf(\"invalid output from AccumulatingSequentialChain\")}\/\/ \u041b\u043e\u0433\u0438\u0440\u0443\u0435\u043c \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0435l.Info(\"[WeatherHandler] AccumulatingSequentialChain completed successfully\")return finalOutput, nil}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h4>4.5. \u0428\u0430\u0433 5: \u0426\u0435\u043f\u043e\u0447\u043a\u0430 1 \u2014 ExtractArgsChain<\/h4>\n<p><strong>\u0417\u0430\u0434\u0430\u0447\u0430:<\/strong> \u0418\u0437\u0432\u043b\u0435\u0447\u044c \u0433\u043e\u0440\u043e\u0434 \u0438 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0434\u043d\u0435\u0439 \u0438\u0437 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430.<\/p>\n<p>\u0417\u0434\u0435\u0441\u044c \u0438 \u0434\u0430\u043b\u0435\u0435 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0448\u0430\u0431\u043b\u043e\u043d\u044b, \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u0438\u0438 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0438 \u0441\u043e\u0437\u0434\u0430\u044e\u0442\u0441\u044f \u043d\u0430\u0448\u0438 \u043f\u0440\u043e\u043c\u043f\u0442\u044b \u043a \u043c\u043e\u0434\u0435\u043b\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044f \u0432 \u043d\u0438\u0445 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043d\u0430\u043c \u0434\u0430\u043d\u043d\u044b\u0435<\/p>\n<p><strong>\u0424\u0430\u0439\u043b:<\/strong> <code>weather\/template.go<\/code><\/p>\n<pre><code class=\"go\">var (\/\/ WeatherPromptTemplate \u2014 \u0448\u0430\u0431\u043b\u043e\u043d \u0434\u043b\u044f \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u044f \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0438\u0437 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.WeatherPromptTemplate prompts.PromptTemplate\/\/ FinalWeatherPromptTemplate \u2014 \u0448\u0430\u0431\u043b\u043e\u043d \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0444\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043e\u0442\u0432\u0435\u0442\u0430 \u0441 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u044f\u043c\u0438.FinalWeatherPromptTemplate prompts.PromptTemplate)\/\/ initTemplates \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442 \u0432\u0441\u0435 \u0448\u0430\u0431\u043b\u043e\u043d\u044b \u043f\u0440\u043e\u043c\u043f\u0442\u043e\u0432.\/\/ \u041a\u0430\u0436\u0434\u044b\u0439 \u0448\u0430\u0431\u043b\u043e\u043d \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0441 \u0442\u0435\u043a\u0441\u0442\u043e\u043c \u043f\u0440\u043e\u043c\u043f\u0442\u0430 \u0438 \u0441\u043f\u0438\u0441\u043a\u043e\u043c \u0442\u0440\u0435\u0431\u0443\u0435\u043c\u044b\u0445 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445.func InitTemplates() {\/\/ \u0418\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u0438\u0440\u0443\u0435\u0442 LLM \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0433\u043e\u0440\u043e\u0434 \u0438 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0434\u043d\u0435\u0439 \u0434\u043b\u044f \u043f\u0440\u043e\u0433\u043d\u043e\u0437\u0430WeatherPromptTemplate = prompts.NewPromptTemplate(`\u0422\u044b \u2014 \u043f\u043e\u043c\u043e\u0449\u043d\u0438\u043a \u043f\u043e \u043f\u043e\u0433\u043e\u0434\u0435. \u0422\u0432\u043e\u044f \u0437\u0430\u0434\u0430\u0447\u0430 \u2014 \u043f\u043e\u043c\u043e\u0447\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0441 \u043f\u0440\u043e\u0433\u043d\u043e\u0437\u043e\u043c \u043f\u043e\u0433\u043e\u0434\u044b \u0438 \u0434\u0430\u0442\u044c \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0438 \u043f\u043e \u043e\u0434\u0435\u0436\u0434\u0435.\u0423 \u0442\u0435\u0431\u044f \u0435\u0441\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a function weather_forecast, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043f\u0440\u043e\u0433\u043d\u043e\u0437 \u043f\u043e\u0433\u043e\u0434\u044b \u043d\u0430 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0434\u043d\u0435\u0439 \u0434\u043b\u044f \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0433\u043e\u0440\u043e\u0434\u0430.\u0418\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438:1. \u041f\u0440\u043e\u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0439 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u0434\u043b\u044f weather_forecast. \u0415\u0441\u043b\u0438 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0434\u043d\u0435\u0439 \u043d\u0435 \u0443\u043a\u0430\u0437\u0430\u043d\u043e, \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0432\u043e\u0437\u044c\u043c\u0438 1.\u0412\u0435\u0440\u043d\u0438 \u043e\u0442\u0432\u0435\u0442 \u0432 \u0432\u0438\u0434\u0435 json\u0417\u0430\u043f\u0440\u043e\u0441 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f: {{.userInput}}`,[]string{\"userInput\"},)\/\/ \u041f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u0442 \u0441\u044b\u0440\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u0440\u043e\u0433\u043d\u043e\u0437\u0430 \u0432 \u043f\u043e\u043d\u044f\u0442\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442 \u0441 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u044f\u043c\u0438FinalWeatherPromptTemplate = prompts.NewPromptTemplate(`\u0422\u044b \u2014 \u043f\u043e\u043c\u043e\u0449\u043d\u0438\u043a \u043f\u043e \u043f\u043e\u0433\u043e\u0434\u0435. \u041f\u043e\u043b\u0443\u0447\u0435\u043d \u043f\u0440\u043e\u0433\u043d\u043e\u0437 \u043f\u043e\u0433\u043e\u0434\u044b \u0434\u043b\u044f \u0433\u043e\u0440\u043e\u0434\u0430 {{.city}} \u043d\u0430 {{.days}} \u0434\u043d\u0435\u0439:{{.forecast}}\u041f\u0440\u043e\u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0439 \u044d\u0442\u043e\u0442 \u043f\u0440\u043e\u0433\u043d\u043e\u0437 \u0432\u044b\u0432\u0435\u0434\u0438 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u044d\u0442\u043e\u0433\u043e \u0433\u043e\u0440\u043e\u0434\u0430 \u0438 \u0434\u0430\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u043a\u0440\u0430\u0442\u043a\u0438\u0439 \u0441\u0432\u043e\u0434\u043d\u044b\u0439 \u043f\u0440\u043e\u0433\u043d\u043e\u0437 \u043d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u0434\u0435\u043d\u044c, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0438 \u043f\u043e \u043e\u0434\u0435\u0436\u0434\u0435 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0435\u0441\u043b\u0438 \u043e\u0436\u0438\u0434\u0430\u0435\u0442\u0441\u044f \u0434\u043e\u0436\u0434\u044c, \u0432\u043e\u0437\u044c\u043c\u0438 \u0437\u043e\u043d\u0442; \u0435\u0441\u043b\u0438 \u0445\u043e\u043b\u043e\u0434\u043d\u043e, \u043d\u0430\u0434\u0435\u043d\u044c \u0442\u0435\u043f\u043b\u0443\u044e \u043a\u0443\u0440\u0442\u043a\u0443). \u0412\u044b\u0432\u0435\u0434\u0438 \u0432\u0441\u0435 \u0432 \u0432\u0438\u0434\u0435 \u0442\u0435\u043a\u0441\u0442\u0430 \u0431\u0435\u0437 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0445 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u0447\u0442\u043e\u0431\u044b \u0447\u0435\u043b\u043e\u0432\u0435\u043a \u043c\u043e\u0433 \u044d\u0442\u043e \u043f\u043e\u043d\u044f\u0442\u044c.`,[]string{\"city\", \"days\", \"forecast\"},)}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0412 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0446\u0435\u043f\u043e\u0447\u043a\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u044f \u043f\u043e\u043d\u044f\u043b \u0447\u0442\u043e \u0432 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435 \u043d\u0435\u0442 \u0442\u0430\u043a\u043e\u0439 \u0446\u0435\u043f\u043e\u0447\u043a\u0438 \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u043b\u0430 \u0431\u044b \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0445 \u0446\u0435\u043f\u043e\u0447\u0435\u043a, \u0430 \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u043b\u0430 \u0431\u044b \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u0446\u0435\u043f\u043e\u0447\u043a\u0443, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u0440\u0435\u0448\u0438\u043b \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u044e \u0446\u0435\u043f\u043e\u0447\u043a\u0443 \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u043b\u0430 \u0431\u044b \u0432\u0441\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0435 \u0432 \u0446\u0435\u043f\u043e\u0447\u043a\u0430\u0445 \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u043b\u0430 \u0431\u044b \u0438\u0445 \u043d\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u044d\u0442\u0430\u043f\u044b, \u0445\u043e\u0442\u044f \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0431\u044b \u0437\u0434\u0435\u0441\u044c \u0438 \u0432\u043d\u0435\u0434\u0440\u0438\u0442\u044c \u043f\u0430\u043c\u044f\u0442\u044c \u0430\u0433\u0435\u043d\u0442\u0430.<\/p>\n<p><strong>\u0424\u0430\u0439\u043b:<\/strong> <code>weather\/chains.go<\/code><\/p>\n<pre><code class=\"go\">\/\/ AccumulatingSequentialChain \u2014 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u0430\u044f \u0446\u0435\u043f\u043e\u0447\u043a\u0430 \u0434\u043b\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0446\u0435\u043f\u043e\u0447\u0435\u043a.\/\/ \u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0439 SequentialChain, \u043d\u0430\u043a\u0430\u043f\u043b\u0438\u0432\u0430\u0435\u0442 \u043a\u043b\u044e\u0447\u0438 \u043c\u0435\u0436\u0434\u0443 \u0448\u0430\u0433\u0430\u043c\u0438,\/\/ \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u044f \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0433\u043e \u044d\u0442\u0430\u043f\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c\u0443\/\/ \u0437\u0434\u0435\u0441\u044c \u043c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0421haintype AccumulatingSequentialChain struct {chains []chains.Chain}\/\/ Call \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0432\u0441\u0435 \u0446\u0435\u043f\u043e\u0447\u043a\u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e, \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u044f \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u043e\u0442 \u043e\u0434\u043d\u043e\u0439 \u043a \u0434\u0440\u0443\u0433\u043e\u0439.func (c *AccumulatingSequentialChain) Call(ctx context.Context, inputs map[string]any, options ...chains.ChainCallOption) (map[string]any, error) {\/\/ \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u0445\u043e\u0434\u043d\u044b\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438result := inputs\/\/ \u041f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043a\u0430\u0436\u0434\u0443\u044e \u0446\u0435\u043f\u043e\u0447\u043a\u0443for _, chain := range c.chains {\/\/ \u0412\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u0442\u0435\u043a\u0443\u0449\u0443\u044e \u0446\u0435\u043f\u043e\u0447\u043a\u0443 \u0441 \u043d\u0430\u043a\u043e\u043f\u043b\u0435\u043d\u043d\u044b\u043c\u0438 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430\u043c\u0438stepResult, err := chains.Call(ctx, chain, result, options...)if err != nil {\/\/ \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0443 \u043f\u0440\u0438 \u043d\u0435\u0443\u0434\u0430\u0447\u0435 \u043b\u044e\u0431\u043e\u0439 \u0446\u0435\u043f\u043e\u0447\u043a\u0438return nil, err}\/\/ \u041e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0435\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0441 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u043c\u0438 (\u043d\u0430\u043a\u043e\u043f\u043b\u0435\u043d\u0438\u0435 \u043a\u043b\u044e\u0447\u0435\u0439)result = mergeMaps(result, stepResult)}return result, nil}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0441\u0430\u043c\u0438\u0445 \u0446\u0435\u043f\u043e\u0447\u0435\u043a:<\/p>\n<pre><code class=\"go\">\/\/ createExtractArgsChain \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u0446\u0435\u043f\u043e\u0447\u043a\u0443 \u0434\u043b\u044f \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u044f \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0438\u0437 \u0437\u0430\u043f\u0440\u043e\u0441\u0430.func createExtractArgsChain(llm llms.Model, l Logger) chains.Chain {return chains.NewTransform(func(ctx context.Context, input map[string]any, _ ...chains.ChainCallOption) (map[string]any, error) {\/\/ \u0418\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u0438\u0437 \u0432\u0445\u043e\u0434\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445userInput, ok := input[\"userInput\"].(string)if !ok {return nil, fmt.Errorf(\"invalid userInput type\")}\/\/ \u041b\u043e\u0433\u0438\u0440\u0443\u0435\u043c \u043d\u0430\u0447\u0430\u043b\u043e \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u044f \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432l.Info(\"[WeatherArgsExtract] Extracting city and days from user input\", \"input\", userInput)\/\/ \u0424\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c \u043f\u0440\u043e\u043c\u043f\u0442 \u0434\u043b\u044f LLM \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0448\u0430\u0431\u043b\u043e\u043d\/\/ WeatherPromptTemplate.Format \u043f\u043e\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 userInput \u0432 \u0448\u0430\u0431\u043b\u043e\u043dprompt, err := WeatherPromptTemplate.Format(map[string]any{\"userInput\": userInput})if err != nil {l.Error(\"[WeatherArgsExtract] Failed to format prompt\", \"error\", err)return nil, err}\/\/ \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0434\u043b\u044f LLMmessages := []llms.MessageContent{llms.TextParts(llms.ChatMessageTypeHuman, prompt),}\/\/ \u041d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c ToolChoice \u0434\u043b\u044f \u043f\u0440\u0438\u043d\u0443\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u044b\u0437\u043e\u0432\u0430 weather_forecasttoolChoice := llms.ToolChoice{Type:     \"function\",Function: &amp;llms.FunctionReference{Name: \"weather_forecast\"},}l.Info(\"[WeatherArgsExtract] Calling LLM with ToolChoice\", \"function\", \"weather_forecast\")\/\/ \u0412\u044b\u0437\u044b\u0432\u0430\u0435\u043c LLM \u0441 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u0438 ToolChoiceresp, err := llm.GenerateContent(ctx, messages,llms.WithTools(AvailableTools),llms.WithToolChoice(toolChoice),)if err != nil {l.Error(\"[WeatherArgsExtract] LLM.GenerateContent failed\", \"error\", err)return nil, err}\/\/ \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e LLM \u0432\u0435\u0440\u043d\u0443\u043b\u0430 \u043e\u0442\u0432\u0435\u0442if len(resp.Choices) == 0 {return nil, fmt.Errorf(\"no response from LLM\")}\/\/ \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043e\u0442\u0432\u0435\u0442 \u043e\u0442 LLMllmResponse := resp.Choices[0].Contentl.Info(\"[WeatherArgsExtract] LLM response received\", \"content_preview\", llmResponse)\/\/ \u0418\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u043c JSON \u0438\u0437 \u043e\u0442\u0432\u0435\u0442\u0430 LLMjsonStr := extractJSON(llmResponse)l.Debug(\"[WeatherArgsExtract] Extracted JSON\", \"json\", jsonStr)\/\/ \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u0441\u044b\u0440\u043e\u0439 JSON \u0434\u043b\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u044d\u0442\u0430\u043f\u0430 \u043f\u0430\u0440\u0441\u0438\u043d\u0433\u0430return map[string]any{\"raw_args\": jsonStr,}, nil},[]string{\"userInput\"},[]string{\"raw_args\"},)}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0440 \u0440\u0430\u0431\u043e\u0442\u044b:<\/strong> \u0412\u0445\u043e\u0434: <code>\"\u041a\u0430\u043a\u0430\u044f \u043f\u043e\u0433\u043e\u0434\u0430 \u0432 \u041c\u043e\u0441\u043a\u0432\u0435 \u043d\u0430 3 \u0434\u043d\u044f?\"<\/code> \u0412\u044b\u0445\u043e\u0434: <code>{\"city\": \"\u041c\u043e\u0441\u043a\u0432\u0430\", \"days\": 3}<\/code><\/p>\n<p>\u0412\u0445\u043e\u0434: <code>\"\u041f\u043e\u043a\u0430\u0436\u0438 \u043f\u043e\u0433\u043e\u0434\u0443 \u0432 \u041f\u0438\u0442\u0435\u0440\u0435\"<\/code> \u0412\u044b\u0445\u043e\u0434: <code>{\"city\": \"\u0421\u0430\u043d\u043a\u0442-\u041f\u0435\u0442\u0435\u0440\u0431\u0443\u0440\u0433\", \"days\": 1}<\/code><\/p>\n<h4>4.6. \u0428\u0430\u0433 6: \u0426\u0435\u043f\u043e\u0447\u043a\u0430 2 \u2014 ParseArgsChain<\/h4>\n<p><strong>\u0417\u0430\u0434\u0430\u0447\u0430:<\/strong> \u0420\u0430\u0441\u043f\u0430\u0440\u0441\u0438\u0442\u044c JSON \u0432 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e.<\/p>\n<p><strong>\u0424\u0430\u0439\u043b:<\/strong> <code>weather\/handler.go<\/code><\/p>\n<pre><code class=\"go\">\/\/ createParseArgsChain \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u0446\u0435\u043f\u043e\u0447\u043a\u0443 \u0434\u043b\u044f \u043f\u0430\u0440\u0441\u0438\u043d\u0433\u0430 JSON \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432.\/\/ \u041f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u0442 \u0441\u044b\u0440\u043e\u0439 JSON \u043e\u0442 LLM \u0432 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 (\u0433\u043e\u0440\u043e\u0434 \u0438 \u0434\u043d\u0438).func createParseArgsChain(l Logger) chains.Chain {return chains.NewTransform(func(ctx context.Context, input map[string]any, _ ...chains.ChainCallOption) (map[string]any, error) {\/\/ \u0418\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u043c \u0441\u044b\u0440\u043e\u0439 JSON \u0438\u0437 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0433\u043e \u044d\u0442\u0430\u043f\u0430rawArgs, ok := input[\"raw_args\"].(string)if !ok {return nil, fmt.Errorf(\"invalid raw_args type\")}\/\/ \u041b\u043e\u0433\u0438\u0440\u0443\u0435\u043c \u0441\u044b\u0440\u043e\u0439 \u0432\u044b\u0432\u043e\u0434 LLMl.Debug(\"[ParseArgs] Raw LLM output\", \"raw\", rawArgs, 200)\/\/ \u0418\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u043c JSON \u0438\u0437 \u0441\u0442\u0440\u043e\u043a\u0438 (\u043d\u0430 \u0441\u043b\u0443\u0447\u0430\u0439 markdown-\u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0438)jsonStr := extractJSON(rawArgs)l.Debug(\"[ParseArgs] Extracted JSON\", \"json\", jsonStr)\/\/ \u041f\u0430\u0440\u0441\u0438\u043c JSON \u0432 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 weatherArgsvar args weatherArgsif err := json.Unmarshal([]byte(jsonStr), &amp;args); err != nil {\/\/ \u041f\u0440\u0438 \u043e\u0448\u0438\u0431\u043a\u0435 \u043f\u0430\u0440\u0441\u0438\u043d\u0433\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044el.Warn(\"[ParseArgs] Failed to parse JSON, using fallback\", \"error\", err)args.City = \"\u0412\u043e\u043b\u0433\u043e\u0433\u0440\u0430\u0434\"args.Days = 1}\/\/ \u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0434\u043b\u044f \u043f\u0443\u0441\u0442\u044b\u0445 \u043f\u043e\u043b\u0435\u0439if args.City == \"\" {args.City = \"\u0412\u043e\u043b\u0433\u043e\u0433\u0440\u0430\u0434\"}if args.Days &lt; 1 || args.Days &gt; 7 {args.Days = 1}\/\/ \u041b\u043e\u0433\u0438\u0440\u0443\u0435\u043c \u0440\u0430\u0441\u043f\u0430\u0440\u0441\u0435\u043d\u043d\u044b\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044bl.Info(\"[ParseArgs] Parsed arguments\", \"city\", args.City, \"days\", args.Days)\/\/ \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u044d\u0442\u0430\u043f\u0430return map[string]any{\"city\": args.City,\"days\": args.Days,}, nil},[]string{\"raw_args\"},[]string{\"city\", \"days\"},)}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>\u0412\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044f:<\/strong><\/p>\n<ul>\n<li>\n<p>\u041f\u0443\u0441\u0442\u043e\u0439 city \u2192 <code>\"\u0412\u043e\u043b\u0433\u043e\u0433\u0440\u0430\u0434\"<\/code><\/p>\n<\/li>\n<li>\n<p>days &lt; 1 \u0438\u043b\u0438 days &gt; 7 \u2192 <code>1<\/code><\/p>\n<\/li>\n<\/ul>\n<h4>4.7. \u0428\u0430\u0433 7: \u0426\u0435\u043f\u043e\u0447\u043a\u0430 3 \u2014 WeatherToolChain<\/h4>\n<p><strong>\u0417\u0430\u0434\u0430\u0447\u0430:<\/strong> \u0412\u044b\u0437\u0432\u0430\u0442\u044c MCP-\u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 <code>weather_forecast<\/code> \u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043f\u0440\u043e\u0433\u043d\u043e\u0437.<\/p>\n<p><strong>\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f MCP \u0441\u0435\u0440\u0432\u0435\u0440\u0430:<\/strong> <strong>\u0424\u0430\u0439\u043b:<\/strong> <code>weather\/mcp.go<\/code><\/p>\n<pre><code class=\"go\">\/\/ InitMCPSession \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442 MCP \u0441\u0435\u0441\u0441\u0438\u044e \u043e\u0434\u0438\u043d \u0440\u0430\u0437 \u043f\u0440\u0438 \u0441\u0442\u0430\u0440\u0442\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044ffunc InitMCPSession(ctx context.Context) error {var initErr errormcpSessionOnce.Do(func() {mcpSessionMu.Lock()defer mcpSessionMu.Unlock()\/\/ \u0421\u043e\u0437\u0434\u0430\u0451\u043c MCP \u043a\u043b\u0438\u0435\u043d\u0442\u0430client := mcp.NewClient(&amp;mcp.Implementation{Name: \"weather-client\", Version: \"1.0.0\"},nil,)\/\/ \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c\u0441\u044f \u043a MCP weather \u0441\u0435\u0440\u0432\u0435\u0440\u0443 \u0447\u0435\u0440\u0435\u0437 stdio\/\/ \u0421\u0435\u0440\u0432\u0435\u0440 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0437\u0430\u043f\u0443\u0449\u0435\u043d \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e: npx -y @dangahagan\/weather-mcp@latestcmd := exec.Command(\"npx\", \"-y\", \"@dangahagan\/weather-mcp@latest\")transport := &amp;mcp.CommandTransport{Command: cmd}var err errormcpSession, err = client.Connect(ctx, transport, nil)if err != nil {initErr = fmt.Errorf(\"failed to connect to MCP weather server: %w\", err)return}})return initErr}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430:<\/p>\n<p><strong>\u0424\u0430\u0439\u043b:<\/strong> <code>weather\/tool.go<\/code><\/p>\n<pre><code class=\"go\">\/\/ createWeatherToolChain \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u0446\u0435\u043f\u043e\u0447\u043a\u0443 \u0434\u043b\u044f \u0432\u044b\u0437\u043e\u0432\u0430 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430 \u043f\u043e\u0433\u043e\u0434\u044b.\/\/ \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u043f\u0440\u043e\u0433\u043d\u043e\u0437 \u043f\u043e\u0433\u043e\u0434\u044b \u0434\u043b\u044f \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0433\u043e \u0433\u043e\u0440\u043e\u0434\u0430 \u043d\u0430 \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0434\u043d\u0435\u0439.func createWeatherToolChain(weatherTool *WeatherForecastTool, l Logger) chains.Chain {return chains.NewTransform(func(ctx context.Context, input map[string]any, _ ...chains.ChainCallOption) (map[string]any, error) {\/\/ \u0418\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u043c \u0433\u043e\u0440\u043e\u0434 \u0438\u0437 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0433\u043e \u044d\u0442\u0430\u043f\u0430city, ok := input[\"city\"].(string)if !ok {return nil, fmt.Errorf(\"invalid city type\")}\/\/ \u041f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0434\u043d\u0435\u0439 \u0432 intdays := convertToInt(input[\"days\"])if days &lt;= 0 {days = 1}\/\/ \u041b\u043e\u0433\u0438\u0440\u0443\u0435\u043c \u0432\u044b\u0437\u043e\u0432 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430 \u043f\u043e\u0433\u043e\u0434\u044bl.Info(\"[WeatherTool] Calling weather_forecast via LLM\", \"city\", city, \"days\", days)\/\/ \u0424\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c JSON-\u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u0434\u043b\u044f \u0432\u044b\u0437\u043e\u0432\u0430 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430argsJSON, _ := json.Marshal(map[string]any{\"city\": city,\"days\": days,})l.Info(\"[WeatherTool] Executing weather_forecast tool\", \"args\", string(argsJSON))\/\/ \u0412\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0433\u043d\u043e\u0437\u0430 \u043f\u043e\u0433\u043e\u0434\u044btoolResult, err := weatherTool.Call(ctx, string(argsJSON))if err != nil {l.Error(\"[WeatherTool] Tool call failed\", \"error\", err)return nil, err}\/\/ \u041b\u043e\u0433\u0438\u0440\u0443\u0435\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0440\u0430\u0431\u043e\u0442\u044b \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430l.Info(\"[WeatherTool] Tool completed\", \"result_preview\", toolResult)\/\/ \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u043f\u0440\u043e\u0433\u043d\u043e\u0437 \u0434\u043b\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u044d\u0442\u0430\u043f\u0430return map[string]any{\"forecast\": toolResult,}, nil},[]string{\"city\", \"days\"},[]string{\"forecast\"},)}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>MCP \u0432\u044b\u0437\u043e\u0432:<\/strong><\/p>\n<pre><code class=\"go\">\/\/ weather\/mcp.gofunc fetchWeatherViaMCP(ctx context.Context, city string, days int) ([]DailyForecast, error) { session, err := getMCPSession() if err != nil {  return nil, fmt.Errorf(\"failed to get MCP session: %w\", err) } \/\/ \u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u0438\u0449\u0435\u043c \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u0433\u043e\u0440\u043e\u0434\u0430 \u0447\u0435\u0440\u0435\u0437 search_location searchParams := &amp;mcp.CallToolParams{  Name: \"search_location\",  Arguments: map[string]any{   \"query\": city,   \"limit\": 1,  }, } searchResult, err := session.CallTool(ctx, searchParams) if err != nil {  return nil, fmt.Errorf(\"search_location failed: %w\", err) } if searchResult.IsError {  return nil, fmt.Errorf(\"search_location returned error: %v\", searchResult) } \/\/ \u041f\u0430\u0440\u0441\u0438\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043f\u043e\u0438\u0441\u043a\u0430 \u0438\u0437 Markdown \u0444\u043e\u0440\u043c\u0430\u0442\u0430 lat, lon := parseLocationFromMarkdown(searchResult) if lat == 0 &amp;&amp; lon == 0 {  return nil, fmt.Errorf(\"city '%s' not found\", city) } \/\/ \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043f\u0440\u043e\u0433\u043d\u043e\u0437 \u0447\u0435\u0440\u0435\u0437 get_forecast forecastParams := &amp;mcp.CallToolParams{  Name: \"get_forecast\",  Arguments: map[string]any{   \"latitude\":    lat,   \"longitude\":   lon,   \"days\":        days,   \"granularity\": \"daily\",  }, } forecastResult, err := session.CallTool(ctx, forecastParams) if err != nil {  return nil, fmt.Errorf(\"get_forecast failed: %w\", err) } if forecastResult.IsError {  return nil, fmt.Errorf(\"get_forecast returned error: %v\", forecastResult) } \/\/ \u041f\u0430\u0440\u0441\u0438\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043f\u0440\u043e\u0433\u043d\u043e\u0437\u0430 return parseForecastResult(forecastResult, days)}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h4>4.8. \u0428\u0430\u0433 8: \u0426\u0435\u043f\u043e\u0447\u043a\u0430 4 \u2014 FinalResponseChain<\/h4>\n<p><strong>\u0417\u0430\u0434\u0430\u0447\u0430:<\/strong> \u0421\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0447\u0435\u043b\u043e\u0432\u0435\u043a\u043e\u0447\u0438\u0442\u0430\u0435\u043c\u044b\u0439 \u043e\u0442\u0432\u0435\u0442 \u0441 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u044f\u043c\u0438.<\/p>\n<pre><code class=\"go\">\/\/ createFinalResponseChain \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u0446\u0435\u043f\u043e\u0447\u043a\u0443 \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0444\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043e\u0442\u0432\u0435\u0442\u0430.func createFinalResponseChain(llm llms.Model) *chains.LLMChain {\/\/ \u0421\u043e\u0437\u0434\u0430\u0451\u043c LLM-\u0446\u0435\u043f\u043e\u0447\u043a\u0443 \u0441 \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u043c FinalWeatherPromptTemplatechain := chains.NewLLMChain(llm,FinalWeatherPromptTemplate,)\/\/ \u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0438\u043c\u044f \u0432\u044b\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u043a\u043b\u044e\u0447\u0430chain.OutputKey = \"text\"return chain}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>\u041f\u043e\u0441\u043b\u0435 \u043f\u0440\u043e\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u0432\u0441\u0435\u0439 \u0446\u0435\u043f\u043e\u0447\u043a\u0438 \u043c\u043e\u0434\u0435\u043b\u044c \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u0432\u043e\u0439 \u043e\u0442\u0432\u0435\u0442:<\/strong><\/p>\n<pre><code>### \u041f\u0440\u043e\u0433\u043d\u043e\u0437 \u043f\u043e\u0433\u043e\u0434\u044b \u043d\u0430 \u043d\u0435\u0434\u0435\u043b\u044e \u0432 \u041d\u043e\u0432\u043e\u0441\u0438\u0431\u0438\u0440\u0441\u043a\u0435\\n\\n**\u0413\u043e\u0440\u043e\u0434:** \u041d\u043e\u0432\u043e\u0441\u0438\u0431\u0438\u0440\u0441\u043a  \\n\\n**\u041f\u043e\u043d\u0435\u0434\u0435\u043b\u044c\u043d\u0438\u043a, 29 \u0430\u043f\u0440\u0435\u043b\u044f 2026 \u0433\u043e\u0434\u0430:**  \\n\u041f\u043e\u0433\u043e\u0434\u0430: \u043e\u0431\u043b\u0430\u0447\u043d\u0430\u044f  \\n\u0422\u0435\u043c\u043f\u0435\u0440\u0430\u0442\u0443\u0440\u0430 \u0432\u043e\u0437\u0434\u0443\u0445\u0430: \u043e\u043a\u043e\u043b\u043e +3\u00b0C  \\n\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0432\u0435\u0442\u0440\u0430: \u0434\u043e 26 \u043c\/\u0441  \\n\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0438: \u0412\u043e\u0437\u044c\u043c\u0438\u0442\u0435 \u0442\u0435\u043f\u043b\u044b\u0439 \u0441\u0432\u0438\u0442\u0435\u0440 \u0438\u043b\u0438 \u043a\u0443\u0440\u0442\u043a\u0443, \u0432\u0435\u0442\u0435\u0440 \u0441\u0438\u043b\u044c\u043d\u044b\u0439, \u0432\u043e\u0437\u043c\u043e\u0436\u0435\u043d \u0434\u0438\u0441\u043a\u043e\u043c\u0444\u043e\u0440\u0442 \u043e\u0442 \u0445\u043e\u043b\u043e\u0434\u0430.\\n\\n**\u0412\u0442\u043e\u0440\u043d\u0438\u043a, 30 \u0430\u043f\u0440\u0435\u043b\u044f 2026 \u0433\u043e\u0434\u0430:**  \\n\u041f\u043e\u0433\u043e\u0434\u0430: \u043e\u0431\u043b\u0430\u0447\u043d\u0430\u044f  \\n\u0422\u0435\u043c\u043f\u0435\u0440\u0430\u0442\u0443\u0440\u0430 \u0432\u043e\u0437\u0434\u0443\u0445\u0430: \u043e\u043a\u043e\u043b\u043e +4\u00b0C  \\n\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0432\u0435\u0442\u0440\u0430: \u0434\u043e 18 \u043c\/\u0441  \\n\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0438: \u041b\u0435\u0433\u043a\u0430\u044f \u043a\u0443\u0440\u0442\u043a\u0430 \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e, \u0432\u0435\u0442\u0440\u0435\u043d\u043e, \u043b\u0443\u0447\u0448\u0435 \u043e\u0434\u0435\u0442\u044c\u0441\u044f \u0442\u0435\u043f\u043b\u0435\u0435.\\n\\n**\u0421\u0440\u0435\u0434\u0430, 1 \u043c\u0430\u044f 2026 \u0433\u043e\u0434\u0430:**  \\n\u041f\u043e\u0433\u043e\u0434\u0430: \u043e\u0431\u043b\u0430\u0447\u043d\u0430\u044f  \\n\u0422\u0435\u043c\u043f\u0435\u0440\u0430\u0442\u0443\u0440\u0430 \u0432\u043e\u0437\u0434\u0443\u0445\u0430: \u043e\u043a\u043e\u043b\u043e +7\u00b0C  \\n\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0432\u0435\u0442\u0440\u0430: \u0434\u043e 21 \u043c\/\u0441  \\n\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0438: \u0422\u0435\u043f\u043b\u0430\u044f \u043e\u0434\u0435\u0436\u0434\u0430 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u0430, \u0432\u0435\u0442\u0435\u0440 \u043e\u0449\u0443\u0442\u0438\u043c\u044b\u0439, \u043e\u0434\u0435\u0432\u0430\u0439\u0442\u0435\u0441\u044c \u0442\u0435\u043f\u043b\u043e.\\n\\n**\u0427\u0435\u0442\u0432\u0435\u0440\u0433, 2 \u043c\u0430\u044f 2026 \u0433\u043e\u0434\u0430:**  \\n\u041f\u043e\u0433\u043e\u0434\u0430: \u043e\u0431\u043b\u0430\u0447\u043d\u0430\u044f  \\n\u0422\u0435\u043c\u043f\u0435\u0440\u0430\u0442\u0443\u0440\u0430 \u0432\u043e\u0437\u0434\u0443\u0445\u0430: \u043e\u043a\u043e\u043b\u043e +8\u00b0C  \\n\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0432\u0435\u0442\u0440\u0430: \u0434\u043e 26 \u043c\/\u0441  \\n\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0438: \u041d\u0430\u0434\u0435\u043d\u044c\u0442\u0435 \u043b\u0435\u0433\u043a\u0443\u044e \u043a\u0443\u0440\u0442\u043a\u0443 \u0438\u043b\u0438 \u0432\u0435\u0442\u0440\u043e\u0432\u043a\u0443, \u0442\u0435\u043c\u043f\u0435\u0440\u0430\u0442\u0443\u0440\u0430 \u043a\u043e\u043c\u0444\u043e\u0440\u0442\u043d\u0430\u044f, \u043d\u043e \u0432\u0435\u0442\u0435\u0440 \u0441\u0438\u043b\u044c\u043d\u044b\u0439.\\n\\n**\u041f\u044f\u0442\u043d\u0438\u0446\u0430, 3 \u043c\u0430\u044f 2026 \u0433\u043e\u0434\u0430:**  \\n\u041f\u043e\u0433\u043e\u0434\u0430: \u043e\u0431\u043b\u0430\u0447\u043d\u0430\u044f  \\n\u0422\u0435\u043c\u043f\u0435\u0440\u0430\u0442\u0443\u0440\u0430 \u0432\u043e\u0437\u0434\u0443\u0445\u0430: \u043e\u043a\u043e\u043b\u043e +9\u00b0C  \\n\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0432\u0435\u0442\u0440\u0430: \u0434\u043e 24 \u043c\/\u0441  \\n\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0438: \u041e\u0434\u0435\u0432\u0430\u0439\u0442\u0435\u0441\u044c \u043b\u0435\u0433\u043a\u043e, \u0432\u0435\u0442\u0435\u0440 \u0443\u043c\u0435\u0440\u0435\u043d\u043d\u044b\u0439, \u043b\u0435\u0433\u043a\u0430\u044f \u0432\u0435\u0440\u0445\u043d\u044f\u044f \u043e\u0434\u0435\u0436\u0434\u0430 \u043f\u043e\u0434\u043e\u0439\u0434\u0435\u0442.\\n\\n**\u0421\u0443\u0431\u0431\u043e\u0442\u0430, 4 \u043c\u0430\u044f 2026 \u0433\u043e\u0434\u0430:**  \\n\u041f\u043e\u0433\u043e\u0434\u0430: \u043e\u0431\u043b\u0430\u0447\u043d\u0430\u044f  \\n\u0422\u0435\u043c\u043f\u0435\u0440\u0430\u0442\u0443\u0440\u0430 \u0432\u043e\u0437\u0434\u0443\u0445\u0430: \u043e\u043a\u043e\u043b\u043e +8\u00b0C  \\n\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0432\u0435\u0442\u0440\u0430: \u0434\u043e 26 \u043c\/\u0441  \\n\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0438: \u0411\u0435\u0440\u0438\u0442\u0435 \u0442\u0435\u043f\u043b\u0443\u044e \u043e\u0434\u0435\u0436\u0434\u0443, \u043f\u043e\u0433\u043e\u0434\u0430 \u043f\u0440\u043e\u0445\u043b\u0430\u0434\u043d\u0430\u044f, \u0432\u0435\u0442\u0435\u0440 \u043f\u043e\u0440\u044b\u0432\u0438\u0441\u0442\u044b\u0439.<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0438\u0434\u0435\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0442 \u043e\u0442\u0432\u0435\u0442\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0443 \u0432 \u0432\u0438\u0434\u0435 JSON<\/p>\n<pre><code class=\"json\">{\"message\":\"\u0417\u0430\u043f\u0440\u043e\u0441 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d\",\"response\":\"### \u041f\u0440\u043e\u0433\u043d\u043e\u0437 \u043f\u043e\u0433\u043e\u0434\u044b \u043d\u0430 \u043d\u0435\u0434\u0435\u043b\u044e \u0432 \u041d\u043e\u0432\u043e\u0441\u0438\u0431\u0438\u0440\u0441\u043a\u0435\\n\\n**\u0413\u043e\u0440\u043e\u0434:** \u041d\u043e\u0432\u043e\u0441\u0438\u0431\u0438\u0440\u0441\u043a  \\n\\n**\u041f\u043e\u043d\u0435\u0434\u0435\u043b\u044c\u043d\u0438\u043a, 29 \u0430\u043f\u0440\u0435\u043b\u044f 2026 \u0433\u043e\u0434\u0430:**  \\n\u041f\u043e\u0433\u043e\u0434\u0430: \u043e\u0431\u043b\u0430\u0447\u043d\u0430\u044f  \\n\u0422\u0435\u043c\u043f\u0435\u0440\u0430\u0442\u0443\u0440\u0430 \u0432\u043e\u0437\u0434\u0443\u0445\u0430: \u043e\u043a\u043e\u043b\u043e +3\u00b0C  \\n\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0432\u0435\u0442\u0440\u0430: \u0434\u043e 26 \u043c\/\u0441  \\n\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0438: \u0412\u043e\u0437\u044c\u043c\u0438\u0442\u0435 \u0442\u0435\u043f\u043b\u044b\u0439 \u0441\u0432\u0438\u0442\u0435\u0440 \u0438\u043b\u0438 \u043a\u0443\u0440\u0442\u043a\u0443, \u0432\u0435\u0442\u0435\u0440 \u0441\u0438\u043b\u044c\u043d\u044b\u0439, \u0432\u043e\u0437\u043c\u043e\u0436\u0435\u043d \u0434\u0438\u0441\u043a\u043e\u043c\u0444\u043e\u0440\u0442 \u043e\u0442 \u0445\u043e\u043b\u043e\u0434\u0430.\\n\\n**\u0412\u0442\u043e\u0440\u043d\u0438\u043a, 30 \u0430\u043f\u0440\u0435\u043b\u044f 2026 \u0433\u043e\u0434\u0430:**  \\n\u041f\u043e\u0433\u043e\u0434\u0430: \u043e\u0431\u043b\u0430\u0447\u043d\u0430\u044f  \\n\u0422\u0435\u043c\u043f\u0435\u0440\u0430\u0442\u0443\u0440\u0430 \u0432\u043e\u0437\u0434\u0443\u0445\u0430: \u043e\u043a\u043e\u043b\u043e +4\u00b0C  \\n\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0432\u0435\u0442\u0440\u0430: \u0434\u043e 18 \u043c\/\u0441  \\n\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0438: \u041b\u0435\u0433\u043a\u0430\u044f \u043a\u0443\u0440\u0442\u043a\u0430 \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e, \u0432\u0435\u0442\u0440\u0435\u043d\u043e, \u043b\u0443\u0447\u0448\u0435 \u043e\u0434\u0435\u0442\u044c\u0441\u044f \u0442\u0435\u043f\u043b\u0435\u0435.\\n\\n**\u0421\u0440\u0435\u0434\u0430, 1 \u043c\u0430\u044f 2026 \u0433\u043e\u0434\u0430:**  \\n\u041f\u043e\u0433\u043e\u0434\u0430: \u043e\u0431\u043b\u0430\u0447\u043d\u0430\u044f  \\n\u0422\u0435\u043c\u043f\u0435\u0440\u0430\u0442\u0443\u0440\u0430 \u0432\u043e\u0437\u0434\u0443\u0445\u0430: \u043e\u043a\u043e\u043b\u043e +7\u00b0C  \\n\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0432\u0435\u0442\u0440\u0430: \u0434\u043e 21 \u043c\/\u0441  \\n\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0438: \u0422\u0435\u043f\u043b\u0430\u044f \u043e\u0434\u0435\u0436\u0434\u0430 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u0430, \u0432\u0435\u0442\u0435\u0440 \u043e\u0449\u0443\u0442\u0438\u043c\u044b\u0439, \u043e\u0434\u0435\u0432\u0430\u0439\u0442\u0435\u0441\u044c \u0442\u0435\u043f\u043b\u043e.\\n\\n**\u0427\u0435\u0442\u0432\u0435\u0440\u0433, 2 \u043c\u0430\u044f 2026 \u0433\u043e\u0434\u0430:**  \\n\u041f\u043e\u0433\u043e\u0434\u0430: \u043e\u0431\u043b\u0430\u0447\u043d\u0430\u044f  \\n\u0422\u0435\u043c\u043f\u0435\u0440\u0430\u0442\u0443\u0440\u0430 \u0432\u043e\u0437\u0434\u0443\u0445\u0430: \u043e\u043a\u043e\u043b\u043e +8\u00b0C  \\n\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0432\u0435\u0442\u0440\u0430: \u0434\u043e 26 \u043c\/\u0441  \\n\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0438: \u041d\u0430\u0434\u0435\u043d\u044c\u0442\u0435 \u043b\u0435\u0433\u043a\u0443\u044e \u043a\u0443\u0440\u0442\u043a\u0443 \u0438\u043b\u0438 \u0432\u0435\u0442\u0440\u043e\u0432\u043a\u0443, \u0442\u0435\u043c\u043f\u0435\u0440\u0430\u0442\u0443\u0440\u0430 \u043a\u043e\u043c\u0444\u043e\u0440\u0442\u043d\u0430\u044f, \u043d\u043e \u0432\u0435\u0442\u0435\u0440 \u0441\u0438\u043b\u044c\u043d\u044b\u0439.\\n\\n**\u041f\u044f\u0442\u043d\u0438\u0446\u0430, 3 \u043c\u0430\u044f 2026 \u0433\u043e\u0434\u0430:**  \\n\u041f\u043e\u0433\u043e\u0434\u0430: \u043e\u0431\u043b\u0430\u0447\u043d\u0430\u044f  \\n\u0422\u0435\u043c\u043f\u0435\u0440\u0430\u0442\u0443\u0440\u0430 \u0432\u043e\u0437\u0434\u0443\u0445\u0430: \u043e\u043a\u043e\u043b\u043e +9\u00b0C  \\n\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0432\u0435\u0442\u0440\u0430: \u0434\u043e 24 \u043c\/\u0441  \\n\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0438: \u041e\u0434\u0435\u0432\u0430\u0439\u0442\u0435\u0441\u044c \u043b\u0435\u0433\u043a\u043e, \u0432\u0435\u0442\u0435\u0440 \u0443\u043c\u0435\u0440\u0435\u043d\u043d\u044b\u0439, \u043b\u0435\u0433\u043a\u0430\u044f \u0432\u0435\u0440\u0445\u043d\u044f\u044f \u043e\u0434\u0435\u0436\u0434\u0430 \u043f\u043e\u0434\u043e\u0439\u0434\u0435\u0442.\\n\\n**\u0421\u0443\u0431\u0431\u043e\u0442\u0430, 4 \u043c\u0430\u044f 2026 \u0433\u043e\u0434\u0430:**  \\n\u041f\u043e\u0433\u043e\u0434\u0430: \u043e\u0431\u043b\u0430\u0447\u043d\u0430\u044f  \\n\u0422\u0435\u043c\u043f\u0435\u0440\u0430\u0442\u0443\u0440\u0430 \u0432\u043e\u0437\u0434\u0443\u0445\u0430: \u043e\u043a\u043e\u043b\u043e +8\u00b0C  \\n\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0432\u0435\u0442\u0440\u0430: \u0434\u043e 26 \u043c\/\u0441  \\n\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0438: \u0411\u0435\u0440\u0438\u0442\u0435 \u0442\u0435\u043f\u043b\u0443\u044e \u043e\u0434\u0435\u0436\u0434\u0443, \u043f\u043e\u0433\u043e\u0434\u0430 \u043f\u0440\u043e\u0445\u043b\u0430\u0434\u043d\u0430\u044f, \u0432\u0435\u0442\u0435\u0440 \u043f\u043e\u0440\u044b\u0432\u0438\u0441\u0442\u044b\u0439.\",\"success\":true}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<hr\/>\n<h3>5. \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0445 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u0432<\/h3>\n<h4>5.1. \u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 llms.Model \u0434\u043b\u044f GigaChat<\/h4>\n<p>LangChainGo \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 <code>llms.Model<\/code>, \u043e \u0447\u0451\u043c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0438 \u0433\u043e\u0432\u043e\u0440\u0438\u043b\u043e\u0441\u044c \u0432 \u0434\u043e\u043a\u043b\u0430\u0434\u0435:<\/p>\n<pre><code class=\"go\">type Model interface {    GenerateContent(        ctx context.Context,         messages []Message,         options ...CallOption,    ) (*Response, error)}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u042f \u043d\u0435 \u0441\u0442\u0430\u043b \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u044e \u0432\u0435\u0440\u0441\u0438\u044e, \u0430 \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0441\u044f \u0443\u0436\u0435 \u0433\u043e\u0442\u043e\u0432\u043e\u0439 \u0438\u0437 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 openai.LLM \u0442\u0430\u043a \u043a\u0430\u043a GigaChat \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c \u0441 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u043c\u0438 \u0442\u0438\u043f\u0430 openai. \u041d\u0443\u0436\u043d\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u0447\u0442\u043e \u043d\u0435\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u043c\u0435\u043d\u043d\u043e GigaChat, \u043c\u043e\u0436\u043d\u043e \u0431\u0440\u0430\u0442\u044c \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u043c\u043e\u0434\u0435\u043b\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u0430 \u0441 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u043c\u0438 \u043a openai,\u0442\u0430\u043a \u043a\u0430\u043a \u0441\u0435\u0439\u0447\u0430\u0441 \u043f\u043e\u0447\u0442\u0438 \u0432\u0441\u0435 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043b\u043b\u043c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442 \u0438\u043b\u0438 \u0447\u0430\u0441\u0442\u0438\u0447\u043d\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442 \u0435\u0433\u043e. \u041d\u043e \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u043c\u043e\u0434\u0435\u043b\u044c \u043d\u0435\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u0430, \u0442\u043e \u0435\u0441\u0442\u044c \u0443\u0436\u0435 \u0433\u043e\u0442\u043e\u0432\u044b\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u043c\u043e\u0434\u0435\u043b\u0435\u0439, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a Ollama, Mistral \u0438 \u0434\u0440\u0443\u0433\u0438\u0435. \u0415\u0441\u043b\u0438 \u0436\u0435 \u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0442 \u0434\u043b\u044f \u0432\u0430\u0448\u0435\u0439 \u043c\u043e\u0434\u0435\u043b\u0438, \u0442\u043e \u0442\u043e\u0433\u0434\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0430\u043c\u043e\u043c\u0443 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 Model.<\/p>\n<h4>5.2. llm.go \u2014 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0430\u0434\u0430\u043f\u0442\u0435\u0440\u0430 GigaChat<\/h4>\n<p>C\u043e\u0437\u0434\u0430\u0435\u043c \u043c\u0435\u0442\u043e\u0434 \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043a \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0439 \u043d\u0430\u043c \u043c\u043e\u0434\u0435\u043b\u0438.<\/p>\n<p><strong>\u0424\u0430\u0439\u043b:<\/strong> <code>llm.go<\/code><\/p>\n<pre><code class=\"go\">const ( model = \"GigaChat-2\" \/\/\u0434\u0430\u043d\u043d\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c \u0441\u0430\u043c\u0430\u044f \u043c\u043b\u0430\u0434\u0448\u0430\u044f \u0432 \u043b\u0438\u043d\u0435\u0439\u043a\u0435, \u0435\u0435 \u0445\u0432\u0430\u0442\u0430\u0435\u0442 \u0447\u0442\u043e\u0431\u044b \u0440\u0435\u0448\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u0443\u044e \u0437\u0430\u0434\u0430\u0447\u0443 \/\/ \u0435\u0441\u043b\u0438 \u0432\u044b \u0440\u0435\u0448\u0430\u0435\u0442\u0435 \u0447\u0442\u043e \u0442\u043e \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u043e\u0435 \u0446\u0435\u043b\u0435\u0441\u043e\u043e\u0431\u0440\u0430\u0437\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u0441\u0442\u0430\u0440\u0448\u0438\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 url   = \"https:\/\/gigachat.devices.sberbank.ru\/api\/v1\")\/\/ func getGigaChatLLM(token string) (*openai.LLM, error) {    \/\/ \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043a \u043c\u043e\u0434\u0435\u043b\u0438 \u043f\u043e url, \u0442\u0430\u043a\u0436\u0435 \u0435\u0441\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u0447\u0435\u0440\u0435\u0437 grpc llm, err := openai.New(openai.WithToken(token), openai.WithBaseURL(url), openai.WithModel(model)) if err != nil {  return nil, err } return llm, nil}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h4>5.3. token.go \u2014 OAuth 2.0 \u0442\u043e\u043a\u0435\u043d\u0438\u0437\u0430\u0446\u0438\u044f<\/h4>\n<p>GigaChat \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 OAuth 2.0. \u0412 \u043c\u043e\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u044f \u043f\u043e\u043b\u0443\u0447\u0430\u044e \u0442\u043e\u043a\u0435\u043d 1 \u0440\u0430\u0437, \u043d\u043e \u0435\u0441\u043b\u0438 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u0440\u0435\u0434\u0443\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0442\u043e\u043a\u0435\u043d\u0430, \u0441\u043e\u0433\u043b\u0430\u0441\u043d\u043e \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u0441\u0440\u043e\u043a \u0435\u0433\u043e \u0436\u0438\u0437\u043d\u0438 30 \u043c\u0438\u043d\u0443\u0442.<\/p>\n<p><strong>\u0424\u0430\u0439\u043b:<\/strong> <code>token.go<\/code><\/p>\n<pre><code class=\"go\">\/\/ getToken \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 acessToken \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043d\u0430\u0448\u0435\u0433\u043e \u043a\u043b\u044e\u0447\u0430func getToken(authKey string) (string, error) {\/\/\u0433\u043e\u0442\u043e\u0432\u0438\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u0430url := tokenUrlmethod := tokenMethodpayload := strings.NewReader(scope)client := &amp;http.Client{}req, err := http.NewRequest(method, url, payload)if err != nil {return \"\", err}req.Header.Add(\"Content-Type\", \"application\/x-www-form-urlencoded\")req.Header.Add(\"Accept\", \"application\/json\")req.Header.Add(\"RqUID\", uuid.New().String())req.Header.Add(\"Authorization\", \"Basic \"+authKey)\/\/ \u0434\u0435\u043b\u0430\u0435\u043c \u0441\u0430\u043c \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0441\u0440\u0435\u0432\u0435\u0440\u0430 \u0421\u0431\u0435\u0440\u0431\u0430\u043d\u043a\u0430 \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0442\u043e\u043a\u0435\u043d\u0430res, err := client.Do(req)if err != nil {return \"\", err}defer res.Body.Close()body, err := io.ReadAll(res.Body)if err != nil {return \"\", err}\/\/\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435var tok Tokerr = json.Unmarshal(body, &amp;tok)if err != nil {return \"\", err}return tok.AcessToken, nil}\/\/ \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0442\u043e\u043a\u0435\u043d\u0430type Tok struct {AcessToken string `json:\"access_token\" db:\"access_token\"`ExpiresAt  int64  `json:\"expires_at\" db:\"expires_at\"`}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h4>5.4. main.go \u2014 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f<\/h4>\n<p>\u0421\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043d\u0430\u0448 \u0441\u0435\u0440\u0432\u0438\u0441<\/p>\n<p><strong>\u0424\u0430\u0439\u043b:<\/strong> <code>main.go<\/code><\/p>\n<pre><code class=\"go\">func main() {\/\/\u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u043b\u043e\u0433\u0433\u0435\u0440l := newLogger(0, true)\/\/\u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044ftoken, ip, port, _, err := getConfig()if err != nil {l.Error(\"\u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0442\u043e\u043a\u0435\u043d \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438!\", \"code\", 404)panic(err)}\/\/ \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c acessTokenacessToken, err := getToken(token)if err != nil {l.Error(\"\u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0442\u043e\u043a\u0435\u043d \u0434\u043e\u0441\u0442\u0443\u043f\u0430!\", \"code\", 404)\/\/panic(err)}\/\/ \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c\u0441\u044f \u043a LLMllm, err := getGigaChatLLM(acessToken)if err != nil {l.Error(\"\u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f \u043a \u043b\u043b\u043c \u043c\u043e\u0434\u0435\u043b\u0438!\", \"code\", 500)}\/\/ \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0438 \u0448\u0430\u0431\u043b\u043e\u043d\u044b weather-\u043f\u0430\u043a\u0435\u0442\u0430weather.InitTools()weather.InitTemplates()\/\/ \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c MCP \u0441\u0435\u0441\u0441\u0438\u044e \u0434\u043b\u044f weather \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430ctx := context.Background()if err := weather.InitMCPSession(ctx); err != nil {l.Warn(\"\u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c MCP weather \u0441\u0435\u0441\u0441\u0438\u044e\", \"error\", err)l.Info(\"weather \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0431\u0443\u0434\u0435\u0442 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d\")} else {l.Info(\"MCP weather \u0441\u0435\u0441\u0441\u0438\u044f \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u0430\")\/\/ \u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u0435 MCP \u0441\u0435\u0441\u0441\u0438\u0438 \u043f\u0440\u0438 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0435defer func() {if err := weather.CloseMCPSession(); err != nil {l.Error(\"\u043e\u0448\u0438\u0431\u043a\u0430 \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u044f MCP \u0441\u0435\u0441\u0441\u0438\u0438\", \"error\", err)}}()}\/\/ \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u0430\u0433\u0435\u043d\u0442\u0430agentInstance := agent.NewWeatherAgent(llm, l)app := fiber.New(fiber.Config{AppName:        \"llm Service\",ServerHeader:   \"llm Service\", \/\/ \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u0434\u043b\u044f \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0430CaseSensitive:  true,          \/\/ \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0447\u0443\u0432\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043a \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0443 \u0432 URLStrictRouting:  true,RequestMethods: []string{\"POST\"}, \/\/ \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0441\u0442\u0440\u043e\u0433\u0443\u044e \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0446\u0438\u044e})api := app.Group(\"\/api\") \/\/ \/api\/\/\u043d\u0435 \u0434\u0430\u0435\u043c \u043f\u0430\u0434\u0430\u0442\u044c \u043d\u0430\u0448\u0435\u043c\u0443 \u0441\u0435\u0440\u0432\u0438\u0441\u0443 \u043f\u0440\u0438 \u043f\u0430\u043d\u0438\u043a\u0435api.Use(recover.New())api.Use(cors.New(cors.Config{AllowHeaders: []string{\"Origin, Content-Type, Accept, Authorization\"},AllowMethods: []string{\"POST\"},}))api.Use(compress.New(compress.Config{Level: compress.LevelBestSpeed, \/\/ 1}))\/\/ \u041f\u0435\u0440\u0435\u0434\u0430\u0451\u043c \u0430\u0433\u0435\u043d\u0442 \u0432 \u0440\u043e\u0443\u0442\u044bnewLLMRoutes(api, l, agentInstance)routes := app.GetRoutes()for _, route := range routes {fmt.Printf(\"%s %s\\n\", route.Method, route.Path)}t := 3 * time.Seconderr = serveServer(app, ip, port, t, l)if err != nil {l.Error(\"Server ListenAndServe error\")panic(err)}}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h3>6. \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 MCP \u0434\u043b\u044f weather-\u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430<\/h3>\n<h4>6.1. \u0427\u0442\u043e \u0442\u0430\u043a\u043e\u0435 MCP (Model Context Protocol)<\/h4>\n<p><strong>MCP<\/strong> \u2014 \u044d\u0442\u043e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u0434\u043b\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0432\u043d\u0435\u0448\u043d\u0438\u0445 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u043a LLM-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c.<\/p>\n<p>\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u044c\u0442\u0435, \u0447\u0442\u043e \u0432\u0430\u0448\u0430 LLM \u2014 \u044d\u0442\u043e \u043c\u043e\u0437\u0433. MCP \u2014 \u044d\u0442\u043e \u0440\u0443\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442:<\/p>\n<ul>\n<li>\n<p>\u0414\u0435\u043b\u0430\u0442\u044c HTTP-\u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043a API<\/p>\n<\/li>\n<li>\n<p>\u0427\u0438\u0442\u0430\u0442\u044c \u0444\u0430\u0439\u043b\u044b<\/p>\n<\/li>\n<li>\n<p>\u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043a\u043e\u0434<\/p>\n<\/li>\n<li>\n<p>\u0420\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u0431\u0430\u0437\u0430\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u0445<\/p>\n<\/li>\n<\/ul>\n<p>\u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 MCP \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u043a weather-\u0441\u0435\u0440\u0432\u0435\u0440\u0443, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043f\u0440\u043e\u0433\u043d\u043e\u0437 \u043f\u043e\u0433\u043e\u0434\u044b.<\/p>\n<h4>6.2. weather\/mcp.go \u2014 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0441\u0435\u0441\u0441\u0438\u0438<\/h4>\n<p><strong>\u0424\u0430\u0439\u043b:<\/strong> <code>weather\/mcp.go<\/code><\/p>\n<p>\u041f\u043e\u043c\u0438\u043c\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u0443\u0436\u0435 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043b\u0438 \u0432\u044b\u0448\u0435 \u0442\u0430\u043a\u0436\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0438 \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u044f \u0441\u0435\u0441\u0441\u0438\u0438 \u0441 mcp \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c.<\/p>\n<pre><code class=\"go\">\/\/ getMCPSession \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0443\u044e MCP \u0441\u0435\u0441\u0441\u0438\u044efunc getMCPSession() (*mcp.ClientSession, error) {mcpSessionMu.Lock()defer mcpSessionMu.Unlock()if mcpSession == nil {return nil, fmt.Errorf(\"MCP session not initialized. Call InitMCPSession first\")}return mcpSession, nil}\/\/ CloseMCPSession \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u0442 MCP \u0441\u0435\u0441\u0441\u0438\u044e (\u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u043f\u0440\u0438 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f)func CloseMCPSession() error {mcpSessionMu.Lock()defer mcpSessionMu.Unlock()if mcpSession != nil {mcpSession.Close()mcpSession = nil}return nil}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0422\u0430\u043a\u0436\u0435 \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u043e mcp:<\/p>\n<pre><code class=\"go\">\/\/ fetchWeatherViaMCP \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u043f\u0440\u043e\u0433\u043d\u043e\u0437 \u043f\u043e\u0433\u043e\u0434\u044b \u0447\u0435\u0440\u0435\u0437 MCP \u0441\u0435\u0440\u0432\u0435\u0440func fetchWeatherViaMCP(ctx context.Context, city string, days int) ([]DailyForecast, error) {session, err := getMCPSession()if err != nil {return nil, fmt.Errorf(\"failed to get MCP session: %w\", err)}\/\/ \u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u0438\u0449\u0435\u043c \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u0433\u043e\u0440\u043e\u0434\u0430 \u0447\u0435\u0440\u0435\u0437 search_locationsearchParams := &amp;mcp.CallToolParams{Name: \"search_location\",Arguments: map[string]any{\"query\": city,\"limit\": 1,},}searchResult, err := session.CallTool(ctx, searchParams)if err != nil {return nil, fmt.Errorf(\"search_location failed: %w\", err)}if searchResult.IsError {return nil, fmt.Errorf(\"search_location returned error: %v\", searchResult)}\/\/ \u041f\u0430\u0440\u0441\u0438\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043f\u043e\u0438\u0441\u043a\u0430 \u0438\u0437 Markdown \u0444\u043e\u0440\u043c\u0430\u0442\u0430lat, lon := parseLocationFromMarkdown(searchResult)if lat == 0 &amp;&amp; lon == 0 {return nil, fmt.Errorf(\"city '%s' not found\", city)}\/\/ \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043f\u0440\u043e\u0433\u043d\u043e\u0437 \u0447\u0435\u0440\u0435\u0437 get_forecastforecastParams := &amp;mcp.CallToolParams{Name: \"get_forecast\",Arguments: map[string]any{\"latitude\":    lat,\"longitude\":   lon,\"days\":        days,\"granularity\": \"daily\",},}forecastResult, err := session.CallTool(ctx, forecastParams)if err != nil {return nil, fmt.Errorf(\"get_forecast failed: %w\", err)}if forecastResult.IsError {return nil, fmt.Errorf(\"get_forecast returned error: %v\", forecastResult)}\/\/ \u041f\u0430\u0440\u0441\u0438\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043f\u0440\u043e\u0433\u043d\u043e\u0437\u0430return parseForecastResult(forecastResult, days)}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h3>7. \u041f\u0440\u0438\u043c\u0435\u0440\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f<\/h3>\n<h4>7.1. \u0422\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0447\u0435\u0440\u0435\u0437 curl<\/h4>\n<p><strong>\u0411\u0430\u0437\u043e\u0432\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441:<\/strong><\/p>\n<pre><code class=\"bash\">curl -X POST http:\/\/localhost:8080\/api\/weather\/process \\  -H \"Content-Type: application\/json\" \\  -d '{\"prompt\": \"\u041a\u0430\u043a\u0430\u044f \u043f\u043e\u0433\u043e\u0434\u0430 \u0432 \u041c\u043e\u0441\u043a\u0432\u0435 \u043d\u0430 3 \u0434\u043d\u044f?\"}'<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h4>7.2. \u0422\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0447\u0435\u0440\u0435\u0437 Bruno<\/h4>\n<p><strong>\u0428\u0430\u0433 1:<\/strong> \u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c <a href=\"https:\/\/www.usebruno.com\/\" rel=\"noopener noreferrer nofollow\">Bruno<\/a> (open-source \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u0430 Postman).<\/p>\n<p><strong>\u0428\u0430\u0433 2:<\/strong><\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/57\/f2\/9e\/57f29e7eb96cbb4f0e3abfb633d3a03c.png\" alt=\"\u0421\u043e\u0437\u0434\u0430\u0451\u043c \u043d\u043e\u0432\u0443\u044e \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044e GigaChat Weather API\" sizes=\"(max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/webt\/57\/f2\/9e\/57f29e7eb96cbb4f0e3abfb633d3a03c.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/webt\/57\/f2\/9e\/57f29e7eb96cbb4f0e3abfb633d3a03c.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0421\u043e\u0437\u0434\u0430\u0451\u043c \u043d\u043e\u0432\u0443\u044e \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044e GigaChat Weather API<\/figcaption><\/div>\n<\/figure>\n<p><strong>\u0428\u0430\u0433 3:<\/strong><\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/62\/88\/6e\/62886e2b589db06f64a18351a3d2c2a3.png\" alt=\"\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441\" sizes=\"(max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/webt\/62\/88\/6e\/62886e2b589db06f64a18351a3d2c2a3.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/webt\/62\/88\/6e\/62886e2b589db06f64a18351a3d2c2a3.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441<\/figcaption><\/div>\n<\/figure>\n<p><strong>\u0428\u0430\u0433 4:<\/strong><\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/8f\/a8\/5c\/8fa85c7dd2b0345375f7fc926fe07f68.png\" alt=\"\u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441 \u0438 \u0432\u0438\u0434\u0438\u043c \u043e\u0442\u0432\u0435\u0442\" sizes=\"(max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/webt\/8f\/a8\/5c\/8fa85c7dd2b0345375f7fc926fe07f68.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/webt\/8f\/a8\/5c\/8fa85c7dd2b0345375f7fc926fe07f68.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441 \u0438 \u0432\u0438\u0434\u0438\u043c \u043e\u0442\u0432\u0435\u0442<\/figcaption><\/div>\n<\/figure>\n<h4>7.3. \u041e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u0439 \u043e\u0442\u0432\u0435\u0442<\/h4>\n<pre><code class=\"json\">{\"message\":\"\u0417\u0430\u043f\u0440\u043e\u0441 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d\",\"response\":\"### \u041f\u0440\u043e\u0433\u043d\u043e\u0437 \u043f\u043e\u0433\u043e\u0434\u044b \u043d\u0430 \u043d\u0435\u0434\u0435\u043b\u044e \u0432 \u041d\u043e\u0432\u043e\u0441\u0438\u0431\u0438\u0440\u0441\u043a\u0435\\n\\n**\u0413\u043e\u0440\u043e\u0434:** \u041d\u043e\u0432\u043e\u0441\u0438\u0431\u0438\u0440\u0441\u043a  \\n\\n**\u041f\u043e\u043d\u0435\u0434\u0435\u043b\u044c\u043d\u0438\u043a, 29 \u0430\u043f\u0440\u0435\u043b\u044f 2026 \u0433\u043e\u0434\u0430:**  \\n\u041f\u043e\u0433\u043e\u0434\u0430: \u043e\u0431\u043b\u0430\u0447\u043d\u0430\u044f  \\n\u0422\u0435\u043c\u043f\u0435\u0440\u0430\u0442\u0443\u0440\u0430 \u0432\u043e\u0437\u0434\u0443\u0445\u0430: \u043e\u043a\u043e\u043b\u043e +3\u00b0C  \\n\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0432\u0435\u0442\u0440\u0430: \u0434\u043e 26 \u043c\/\u0441  \\n\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0438: \u0412\u043e\u0437\u044c\u043c\u0438\u0442\u0435 \u0442\u0435\u043f\u043b\u044b\u0439 \u0441\u0432\u0438\u0442\u0435\u0440 \u0438\u043b\u0438 \u043a\u0443\u0440\u0442\u043a\u0443, \u0432\u0435\u0442\u0435\u0440 \u0441\u0438\u043b\u044c\u043d\u044b\u0439, \u0432\u043e\u0437\u043c\u043e\u0436\u0435\u043d \u0434\u0438\u0441\u043a\u043e\u043c\u0444\u043e\u0440\u0442 \u043e\u0442 \u0445\u043e\u043b\u043e\u0434\u0430.\\n\\n**\u0412\u0442\u043e\u0440\u043d\u0438\u043a, 30 \u0430\u043f\u0440\u0435\u043b\u044f 2026 \u0433\u043e\u0434\u0430:**  \\n\u041f\u043e\u0433\u043e\u0434\u0430: \u043e\u0431\u043b\u0430\u0447\u043d\u0430\u044f  \\n\u0422\u0435\u043c\u043f\u0435\u0440\u0430\u0442\u0443\u0440\u0430 \u0432\u043e\u0437\u0434\u0443\u0445\u0430: \u043e\u043a\u043e\u043b\u043e +4\u00b0C  \\n\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0432\u0435\u0442\u0440\u0430: \u0434\u043e 18 \u043c\/\u0441  \\n\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0438: \u041b\u0435\u0433\u043a\u0430\u044f \u043a\u0443\u0440\u0442\u043a\u0430 \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e, \u0432\u0435\u0442\u0440\u0435\u043d\u043e, \u043b\u0443\u0447\u0448\u0435 \u043e\u0434\u0435\u0442\u044c\u0441\u044f \u0442\u0435\u043f\u043b\u0435\u0435.\\n\\n**\u0421\u0440\u0435\u0434\u0430, 1 \u043c\u0430\u044f 2026 \u0433\u043e\u0434\u0430:**  \\n\u041f\u043e\u0433\u043e\u0434\u0430: \u043e\u0431\u043b\u0430\u0447\u043d\u0430\u044f  \\n\u0422\u0435\u043c\u043f\u0435\u0440\u0430\u0442\u0443\u0440\u0430 \u0432\u043e\u0437\u0434\u0443\u0445\u0430: \u043e\u043a\u043e\u043b\u043e +7\u00b0C  \\n\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0432\u0435\u0442\u0440\u0430: \u0434\u043e 21 \u043c\/\u0441  \\n\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0438: \u0422\u0435\u043f\u043b\u0430\u044f \u043e\u0434\u0435\u0436\u0434\u0430 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u0430, \u0432\u0435\u0442\u0435\u0440 \u043e\u0449\u0443\u0442\u0438\u043c\u044b\u0439, \u043e\u0434\u0435\u0432\u0430\u0439\u0442\u0435\u0441\u044c \u0442\u0435\u043f\u043b\u043e.\\n\\n**\u0427\u0435\u0442\u0432\u0435\u0440\u0433, 2 \u043c\u0430\u044f 2026 \u0433\u043e\u0434\u0430:**  \\n\u041f\u043e\u0433\u043e\u0434\u0430: \u043e\u0431\u043b\u0430\u0447\u043d\u0430\u044f  \\n\u0422\u0435\u043c\u043f\u0435\u0440\u0430\u0442\u0443\u0440\u0430 \u0432\u043e\u0437\u0434\u0443\u0445\u0430: \u043e\u043a\u043e\u043b\u043e +8\u00b0C  \\n\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0432\u0435\u0442\u0440\u0430: \u0434\u043e 26 \u043c\/\u0441  \\n\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0438: \u041d\u0430\u0434\u0435\u043d\u044c\u0442\u0435 \u043b\u0435\u0433\u043a\u0443\u044e \u043a\u0443\u0440\u0442\u043a\u0443 \u0438\u043b\u0438 \u0432\u0435\u0442\u0440\u043e\u0432\u043a\u0443, \u0442\u0435\u043c\u043f\u0435\u0440\u0430\u0442\u0443\u0440\u0430 \u043a\u043e\u043c\u0444\u043e\u0440\u0442\u043d\u0430\u044f, \u043d\u043e \u0432\u0435\u0442\u0435\u0440 \u0441\u0438\u043b\u044c\u043d\u044b\u0439.\\n\\n**\u041f\u044f\u0442\u043d\u0438\u0446\u0430, 3 \u043c\u0430\u044f 2026 \u0433\u043e\u0434\u0430:**  \\n\u041f\u043e\u0433\u043e\u0434\u0430: \u043e\u0431\u043b\u0430\u0447\u043d\u0430\u044f  \\n\u0422\u0435\u043c\u043f\u0435\u0440\u0430\u0442\u0443\u0440\u0430 \u0432\u043e\u0437\u0434\u0443\u0445\u0430: \u043e\u043a\u043e\u043b\u043e +9\u00b0C  \\n\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0432\u0435\u0442\u0440\u0430: \u0434\u043e 24 \u043c\/\u0441  \\n\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0438: \u041e\u0434\u0435\u0432\u0430\u0439\u0442\u0435\u0441\u044c \u043b\u0435\u0433\u043a\u043e, \u0432\u0435\u0442\u0435\u0440 \u0443\u043c\u0435\u0440\u0435\u043d\u043d\u044b\u0439, \u043b\u0435\u0433\u043a\u0430\u044f \u0432\u0435\u0440\u0445\u043d\u044f\u044f \u043e\u0434\u0435\u0436\u0434\u0430 \u043f\u043e\u0434\u043e\u0439\u0434\u0435\u0442.\\n\\n**\u0421\u0443\u0431\u0431\u043e\u0442\u0430, 4 \u043c\u0430\u044f 2026 \u0433\u043e\u0434\u0430:**  \\n\u041f\u043e\u0433\u043e\u0434\u0430: \u043e\u0431\u043b\u0430\u0447\u043d\u0430\u044f  \\n\u0422\u0435\u043c\u043f\u0435\u0440\u0430\u0442\u0443\u0440\u0430 \u0432\u043e\u0437\u0434\u0443\u0445\u0430: \u043e\u043a\u043e\u043b\u043e +8\u00b0C  \\n\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0432\u0435\u0442\u0440\u0430: \u0434\u043e 26 \u043c\/\u0441  \\n\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0438: \u0411\u0435\u0440\u0438\u0442\u0435 \u0442\u0435\u043f\u043b\u0443\u044e \u043e\u0434\u0435\u0436\u0434\u0443, \u043f\u043e\u0433\u043e\u0434\u0430 \u043f\u0440\u043e\u0445\u043b\u0430\u0434\u043d\u0430\u044f, \u0432\u0435\u0442\u0435\u0440 \u043f\u043e\u0440\u044b\u0432\u0438\u0441\u0442\u044b\u0439.\",\"success\":true}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h3>8. \u0418\u0442\u043e\u0433\u0438<\/h3>\n<h4>8.1. \u0427\u0442\u043e \u0431\u044b\u043b\u043e \u0441\u0434\u0435\u043b\u0430\u043d\u043e<\/h4>\n<p><strong>\u0420\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u0430 \u043f\u043e\u043b\u043d\u0430\u044f \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f GigaChat + LangChainGo<\/strong><\/p>\n<ul>\n<li>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043c\u043e\u0434\u0435\u043b\u0438 \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 <code>llms.Model<\/code> \u0447\u0435\u0440\u0435\u0437 openai.LLM<\/p>\n<\/li>\n<li>\n<p>\u0420\u0430\u0431\u043e\u0442\u0430 \u0441 \u0446\u0435\u043f\u043e\u0447\u043a\u0430\u043c\u0438 (chains)<\/p>\n<\/li>\n<li>\n<p>\u0412\u044b\u0437\u043e\u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0430\u0433\u0435\u043d\u0442\u0430<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u0421\u043e\u0437\u0434\u0430\u043d \u0440\u0430\u0431\u043e\u0447\u0438\u0439 HTTP-\u0441\u0435\u0440\u0432\u0435\u0440<\/strong><\/p>\n<p><strong>\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0430 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 MCP<\/strong><\/p>\n<ul>\n<li>\n<p>\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0432\u043d\u0435\u0448\u043d\u0438\u0445 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432<\/p>\n<\/li>\n<\/ul>\n<h4>8.2. \u0427\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0443\u043b\u0443\u0447\u0448\u0438\u0442\u044c<\/h4>\n<ul>\n<li>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0434\u0440\u0443\u0433\u0438\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b<\/p>\n<\/li>\n<li>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u044d\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0442\u0432\u0435\u0442\u043e\u0432<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0430\u0442\u044c streaming \u043e\u0442\u0432\u0435\u0442\u043e\u0432<\/p>\n<\/li>\n<li>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u0430\u043c\u044f\u0442\u044c \u0438 \u0438\u0441\u0442\u043e\u0440\u0438\u044e \u0447\u0430\u0442\u043e\u0432<\/p>\n<\/li>\n<\/ul>\n<p>\u041d\u0443\u0436\u043d\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u0447\u0442\u043e \u0441\u043e\u0433\u043b\u0430\u0441\u043d\u043e GigaChat API \u0442\u0430\u043a\u0436\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u044d\u0442\u043e\u0433\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430 \u043f\u043e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0443 GRPC.<\/p>\n<h3>9. \u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h3>\n<p>\u0414\u043e\u043a\u043b\u0430\u0434 \u0410\u043d\u0442\u043e\u043d\u0430 \u042e\u0440\u0447\u0435\u043d\u043a\u043e \u0434\u0430\u043b \u043e\u0442\u043b\u0438\u0447\u043d\u0443\u044e \u0438\u0434\u0435\u044e, \u043d\u043e \u043d\u0435 \u0445\u0432\u0430\u0442\u0430\u043b\u043e <strong>\u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043a\u043e\u0434\u0430<\/strong>. \u042d\u0442\u043e\u0442 \u043f\u0440\u043e\u0435\u043a\u0442 \u2014 \u043f\u043e\u043f\u044b\u0442\u043a\u0430 \u0432\u043e\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u044d\u0442\u043e\u0442 \u043f\u0440\u043e\u0431\u0435\u043b.<\/p>\n<p><strong>\u0413\u043b\u0430\u0432\u043d\u044b\u0439 \u0432\u044b\u0432\u043e\u0434:<\/strong> \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f GigaChat \u0441 LangChainGo \u2014 \u044d\u0442\u043e \u043d\u0435 \u0442\u0430\u043a \u0441\u0442\u0440\u0430\u0448\u043d\u043e, \u043a\u0430\u043a \u043a\u0430\u0436\u0435\u0442\u0441\u044f. \u042d\u0442\u043e\u0442 \u043a\u043e\u0434 \u2014 \u0433\u043e\u0442\u043e\u0432\u0430\u044f \u043e\u0441\u043d\u043e\u0432\u0430 \u0434\u043b\u044f pet-\u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432. \u0411\u0435\u0440\u0438\u0442\u0435, \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u0443\u0439\u0442\u0435, \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0439\u0442\u0435 \u0441\u0432\u043e\u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b. \u0411\u0443\u0434\u0443 \u0440\u0430\u0434 \u043e\u0431\u0441\u0443\u0434\u0438\u0442\u044c \u0432\u0430\u0448 \u043e\u043f\u044b\u0442 \u0441 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435\u043c \u0430\u0433\u0435\u043d\u0442\u043e\u0432.<\/p>\n<h3>\u041f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/h3>\n<h4>\u0410. \u041f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0441\u0441\u044b\u043b\u043a\u0438<\/h4>\n<ul>\n<li>\n<p><strong>LangChainGo Docs:<\/strong> <a href=\"https:\/\/github.com\/tmc\/langchaingo\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/tmc\/langchaingo<\/a><\/p>\n<\/li>\n<li>\n<p><strong>GigaChat API:<\/strong> <a href=\"https:\/\/developers.sber.ru\/docs\/ru\/gigachat\" rel=\"noopener noreferrer nofollow\">https:\/\/developers.sber.ru\/docs\/ru\/gigachat<\/a><\/p>\n<\/li>\n<li>\n<p><strong>MCP Protocol:<\/strong> <a href=\"https:\/\/modelcontextprotocol.io\/\" rel=\"noopener noreferrer nofollow\">https:\/\/modelcontextprotocol.io\/<\/a><\/p>\n<\/li>\n<li>\n<p><strong>Fiber v3:<\/strong> <a href=\"https:\/\/docs.gofiber.io\/\" rel=\"noopener noreferrer nofollow\">https:\/\/docs.gofiber.io\/<\/a><\/p>\n<\/li>\n<li>\n<p><strong>Bruno:<\/strong> <a href=\"https:\/\/www.usebruno.com\/\" rel=\"noopener noreferrer nofollow\">https:\/\/www.usebruno.com\/<\/a><\/p>\n<\/li>\n<\/ul>\n<h4>\u0412. \u0418\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434<\/h4>\n<p><strong>\u0420\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439:<\/strong> <a href=\"https:\/\/github.com\/art9276\/weather-agent-mcp\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/art9276\/weather-agent-mcp<\/a><\/p>\n<\/div>\n<p>\u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/1033718\/\">https:\/\/habr.com\/ru\/articles\/1033718\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u041e\u0442 \u0430\u0432\u0442\u043e\u0440\u0430: \u042d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u0440\u043e\u0434\u0438\u043b\u0430\u0441\u044c \u0438\u0437 \u0436\u0435\u043b\u0430\u043d\u0438\u044f \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0437\u0430 \u043a\u0430\u0434\u0440\u043e\u043c \u043e\u0442\u043b\u0438\u0447\u043d\u043e\u0433\u043e \u0434\u043e\u043a\u043b\u0430\u0434\u0430.1. \u0412\u0432\u0435\u0434\u0435\u043d\u0438\u04351.1. \u0418\u0441\u0442\u043e\u0440\u0438\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0412\u0441\u0451 \u043d\u0430\u0447\u0430\u043b\u043e\u0441\u044c \u0441 \u0434\u043e\u043a\u043b\u0430\u0434\u0430 \u0410\u043d\u0442\u043e\u043d\u0430 \u042e\u0440\u0447\u0435\u043d\u043a\u043e \u00ab\u0423\u043b\u0443\u0447\u0448\u0430\u0435\u043c \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u043e \u043e\u0442\u0447\u0451\u0442\u043e\u0432 \u043d\u0430\u0433\u0440\u0443\u0437\u043e\u0447\u043d\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Go, LangChain \u0438 GigaChat\u00bb.\u0414\u043e\u043a\u043b\u0430\u0434 \u043c\u043d\u0435 \u043f\u043e\u043d\u0440\u0430\u0432\u0438\u043b\u0441\u044f: \u0447\u0451\u0442\u043a\u0430\u044f \u043f\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b, \u0433\u0440\u0430\u043c\u043e\u0442\u043d\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u043a \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438, \u043e\u0442\u043b\u0438\u0447\u043d\u0430\u044f \u0438\u0434\u0435\u044f \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c LLM \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0447\u0435\u043b\u043e\u0432\u0435\u043a\u043e\u043f\u043e\u043d\u044f\u0442\u043d\u044b\u0445 \u043e\u0442\u0447\u0451\u0442\u043e\u0432. \u041d\u043e \u043f\u043e\u0441\u043b\u0435 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 \u043e\u0441\u0442\u0430\u043b\u0430\u0441\u044c \u043e\u0434\u043d\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u2014 \u043a\u043e\u0434 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u0442\u0430\u043a \u0438 \u043d\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u0438.\u0411\u044b\u043b\u043e \u0441\u043a\u0430\u0437\u0430\u043d\u043e \u043b\u0438\u0448\u044c, \u0447\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u00ab\u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u00bb \u0434\u043b\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f GigaChat \u043a LangChain. \u0417\u0432\u0443\u0447\u0438\u0442 \u043f\u0440\u043e\u0441\u0442\u043e, \u043d\u043e \u043a\u043e\u0433\u0434\u0430 \u0442\u044b \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0448\u044c \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e LangChainGo, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043a \u0441\u043b\u043e\u0432\u0443 \u0435\u0449\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u043f\u043e\u043b\u043e\u0432\u0438\u043d\u0443 \u0438 \u043f\u044b\u0442\u0430\u0435\u0448\u044c\u0441\u044f \u043f\u043e\u043d\u044f\u0442\u044c, \u0441 \u0447\u0435\u0433\u043e \u043d\u0430\u0447\u0430\u0442\u044c \u2014 \u0432\u043e\u0437\u043d\u0438\u043a \u0432\u043e\u043f\u0440\u043e\u0441: \u041a\u0430\u043a\u043e\u0439 \u0438\u043c\u0435\u043d\u043d\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c? \u0414\u0430\u043b\u0435\u0435 \u043f\u043e \u0438\u0437\u0443\u0447\u0435\u043d\u0438\u044e \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438  \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u0438 \u0438 \u0434\u0440\u0443\u0433\u0438\u0435:\u0427\u0442\u043e \u0442\u0430\u043a\u043e\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0432 LLM \u0438 \u043a\u0430\u043a \u0438\u0445 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c?\u041a\u0430\u043a \u0441\u0432\u044f\u0437\u0430\u0442\u044c \u044d\u0442\u043e \u0432\u0441\u0451 \u0441 \u0446\u0435\u043f\u043e\u0447\u043a\u0430\u043c\u0438 (chains) \u0438 \u0437\u0430\u0447\u0435\u043c \u043e\u043d\u0438 \u0432\u043e\u043e\u0431\u0449\u0435 \u043d\u0443\u0436\u043d\u044b?\u0427\u0442\u043e \u0442\u0430\u043a\u043e\u0435 \u0448\u0430\u0431\u043b\u043e\u043d \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0438 \u043d\u0443\u0436\u043d\u043e \u043b\u0438 \u043c\u043d\u0435 \u0438\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f?\u0422\u0430\u043a \u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f \u044d\u0442\u043e\u0442 pet-\u043f\u0440\u043e\u0435\u043a\u0442. \u042f \u0440\u0435\u0448\u0438\u043b \u0441\u0430\u043c \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f \u0438 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0447\u0438\u0439 \u043f\u0440\u0438\u043c\u0435\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0442\u0440\u043e\u0433\u0430\u0442\u044c, \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0438 \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u0442\u044c.1.2. \u0426\u0435\u043b\u044c \u0441\u0442\u0430\u0442\u044c\u0438\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0447\u0438\u0439 \u043a\u043e\u0434 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 GigaChat \u0441 LangChainGo \u043d\u0430 Go. \u0412 \u043d\u0451\u043c \u044f \u0445\u043e\u0447\u0443 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0443\u043a\u0430\u0437\u0430\u043d\u043e \u0432 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u0445 \u043a\u0430\u043a \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438, \u0442\u0430\u043a \u0438 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 GigaChat, \u0430 \u0438\u043c\u0435\u043d\u043d\u043e \u0441\u0435\u0440\u0432\u0438\u0441 \u043f\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044e \u043f\u043e\u0433\u043e\u0434\u044b, \u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0437\u0430\u043f\u0440\u043e\u0441 \u043a \u043c\u043e\u0434\u0435\u043b\u0438, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043e\u0442\u0434\u0430\u0441\u0442 \u043c\u043d\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0433\u0430\u043b\u043b\u044e\u0446\u0438\u043d\u0430\u0446\u0438\u0438, \u0430 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0438 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435. \u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0430\u0433\u0435\u043d\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0438\u0437 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0433\u043e\u0440\u043e\u0434 \u0438 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0434\u043d\u0435\u0439 \u0434\u043b\u044f \u043f\u0440\u043e\u0433\u043d\u043e\u0437\u0430, \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c  \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u043e\u0433\u043d\u043e\u0437 \u043f\u043e\u0433\u043e\u0434\u044b \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e mcp-\u0441\u0435\u0440\u0432\u0435\u0440\u0430 ,\u0430 \u0437\u0430\u0442\u0435\u043c \u0443\u0436\u0435 \u0438\u043c\u0435\u044f \u0432\u0441\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0433\u043d\u043e\u0437 \u0438 \u0434\u0430\u0432\u0430\u0442\u044c \u0441\u043e\u0432\u0435\u0442 \u043f\u043e \u043e\u0434\u0435\u0436\u0434\u0435, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043e\u0434\u0435\u0442\u044c \u043d\u0430 \u0443\u043b\u0438\u0446\u0443.2. \u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430: \u0447\u0442\u043e \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f2.1. \u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438\u0414\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0430\u0433\u0435\u043d\u0442\u0430 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 github.com\/tmc\/langchaingo, \u0435\u0449\u0451 \u0432 \u0440\u0430\u0431\u043e\u0442\u0435 \u0430\u0433\u0435\u043d\u0442\u0430 \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f:mcp \u0441\u0435\u0440\u0432\u0435\u0440 \u043f\u043e\u0433\u043e\u0434\u044b\u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0434\u043b\u044f \u0435\u0433\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f github.com\/modelcontextprotocol\/go-sdk\/mcpGigaChat &#8212; \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0441\u0430\u043c\u0430 \u043c\u043e\u0434\u0435\u043b\u044cNode.js &#8212; \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b mcp \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043f\u043e\u0433\u043e\u0434\u044b.2.2. \u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u0432 Sber Developers\u0414\u043b\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a GigaChat API \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0430\u043a\u043a\u0430\u0443\u043d\u0442 \u0432 Sber Developers \u0438 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0442\u0430\u043c \u0441\u0432\u043e\u0439 \u043f\u0440\u043e\u0435\u043a\u0442.\u0428\u0430\u0433 1: \u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043d\u0430 developers.sber.ru, \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c\u0441\u044f \u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0443\u0435\u043c\u0441\u044f.\u0428\u0430\u0433 2:\u0412\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442.\u0428\u0430\u0433 3:\u0412\u044b\u0431\u0438\u0440\u0430\u0435\u043c AI-\u043c\u043e\u0434\u0435\u043b\u0438 -&gt; GigaChat API\u0428\u0430\u0433 4:\u0417\u0430\u0445\u043e\u0434\u0438\u043c \u0432 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442\u0428\u0430\u0433 5:\u0412\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c API \u0438 \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043d\u043e\u0432\u044b\u0439 \u043a\u043b\u044e\u04472.3. \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0438 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442 weather-agentgo mod init weather-agentC\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430:\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u04303. \u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f3.1. \u041e\u0431\u0449\u0430\u044f \u0441\u0445\u0435\u043c\u0430\u041d\u0435\u043c\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0432\u0448\u0438\u0441\u044c \u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 langchaingo \u044f \u0443\u0437\u043d\u0430\u043b, \u0447\u0442\u043e \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u043b\u044e\u0431\u043e\u0439 \u0430\u0433\u0435\u043d\u0442 \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432:\u041c\u043e\u0434\u0435\u043b\u044c, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u043e\u0441\u043d\u043e\u0432\u043e\u0439 \u0430\u0433\u0435\u043d\u0442\u0430 (Model)\u0424\u0443\u043d\u043a\u0446\u0438\u0438 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u043d\u0430 \u0443\u043c\u0435\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c (Tools)\u041f\u0430\u043c\u044f\u0442\u044c \u043c\u043e\u0434\u0435\u043b\u0438 (Brain)\u0426\u0435\u043f\u043e\u0447\u043a\u0438 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u0430\u0433\u0435\u043d\u0442\u0430 (Chain)\u042d\u0442\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435  \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0430\u0433\u0435\u043d\u0442\u0430 \u0438 \u0438\u0445 \u043c\u043e\u0436\u043d\u043e \u043a\u043e\u043c\u0431\u0438\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c, \u0430 \u0447\u0442\u043e\u0431\u044b \u0430\u0433\u0435\u043d\u0442 \u0431\u044b\u043b \u0431\u043e\u043b\u0435\u0435 \u0434\u0435\u0442\u0435\u0440\u043c\u0438\u043d\u0438\u0440\u043e\u0432\u0430\u043d, \u043c\u044b \u043a\u0430\u043a \u0438 \u0432 \u043e\u0431\u044b\u043a\u043d\u043e\u0432\u0435\u043d\u043d\u043e\u0439 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0435 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0435\u043c\u0443 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0446\u0435\u043f\u043e\u0447\u043a\u0430. \u0421\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044f \u044d\u0442\u0438 \u0446\u0435\u043f\u043e\u0447\u043a\u0438 \u043c\u044b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0440\u0430\u0431\u043e\u0442\u044b \u0430\u0433\u0435\u043d\u0442\u0430, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u0435\u043c \u0434\u0435\u043b\u0430\u0442\u044c \u0432\u043e\u0437\u0432\u0440\u0430\u0442 \u043a \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0439 \u043d\u0430\u043c \u0447\u0430\u0441\u0442\u0438 \u0446\u0435\u043f\u043e\u0447\u043a\u0438 \u043f\u0440\u0438 \u0441\u0431\u043e\u0435, \u0438\u043b\u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u0435\u043d\u0438\u044e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0435\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430. \u042f \u0440\u0435\u0448\u0438\u043b \u043d\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u043f\u0430\u043c\u044f\u0442\u044c \u0432 \u0441\u0432\u043e\u0435\u0433\u043e \u0430\u0433\u0435\u043d\u0442\u0430, \u0442\u0430\u043a \u043a\u0430\u043a \u044d\u0442\u043e \u043d\u0435 \u043e\u0441\u043e\u0431\u043e \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u043f\u0440\u043e\u0433\u043d\u043e\u0437\u0430 \u043f\u043e\u0433\u043e\u0434\u044b, \u043d\u043e \u043f\u0440\u0438 \u0436\u0435\u043b\u0430\u043d\u0438\u0438 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u043f\u0430\u043c\u044f\u0442\u0438 \u0435\u0441\u043b\u0438 \u0432\u0430\u043c \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e.\u0421\u0445\u0435\u043c\u0430 \u0440\u0430\u0431\u043e\u0442\u044b \u0430\u0433\u0435\u043d\u0442\u04303.2. \u041a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044bGigaChatLLM &#8212; \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 llms.Model \u0434\u043b\u044f GigaChat, Agent &#8212; \u041a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u043e\u0440 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0438 \u0438\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c \u0446\u0435\u043f\u043e\u0447\u0435\u043a (WeatherAgent), Chains &#8212; \u0426\u0435\u043f\u043e\u0447\u043a\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432, Tools &#8212; \u0412\u043d\u0435\u0448\u043d\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 (weather \u0447\u0435\u0440\u0435\u0437 MCP), MCP Client &#8212; \u041a\u043b\u0438\u0435\u043d\u0442 \u0434\u043b\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043a weather-\u0441\u0435\u0440\u0432\u0435\u0440\u04434. \u041f\u043e\u0442\u043e\u043a \u0434\u0430\u043d\u043d\u044b\u0445: \u043e\u0442 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0434\u043e \u043e\u0442\u0432\u0435\u0442\u0430\u0420\u0430\u0437\u0431\u0435\u0440\u0451\u043c \u043f\u043e\u043b\u043d\u044b\u0439 \u043f\u0443\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435: \u00ab\u041a\u0430\u043a\u0430\u044f \u043f\u043e\u0433\u043e\u0434\u0430 \u0432 \u041c\u043e\u0441\u043a\u0432\u0435 \u043d\u0430 3 \u0434\u043d\u044f?\u00bb4.1. \u0428\u0430\u0433 1: HTTP-\u0437\u0430\u043f\u0440\u043e\u0441 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044fPOST http:\/\/localhost:8080\/api\/weather\/processContent-Type: application\/json{  &#171;prompt&#187;: &#171;\u041a\u0430\u043a\u0430\u044f \u043f\u043e\u0433\u043e\u0434\u0430 \u0432 \u041d\u043e\u0432\u043e\u0441\u0438\u0431\u0438\u0440\u0441\u043a\u0435 \u043d\u0430 7 \u0434\u043d\u0435\u0439?&#187;}4.2. \u0428\u0430\u0433 2: \u041a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 (controller.go)\u0424\u0430\u0439\u043b: controller.goconst (weatherProcessRoute = &#171;\/weather\/process&#187; )\/\/ AgentRequest \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441 \u043a \u0430\u0433\u0435\u043d\u0442\u0443 \u0441 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u043c \u043f\u0440\u043e\u043c\u043f\u0442\u043e\u043c.type AgentRequest struct {Prompt string `json:&#187;prompt&#187;` \/\/ \u0422\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f}\/\/ llmRoutes \u0445\u0440\u0430\u043d\u0438\u0442 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043a LLM.type llmRoutes struct {l     *slog.Logger        \/\/ l \u2014 \u043b\u043e\u0433\u0433\u0435\u0440 \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0439agent *agent.WeatherAgent \/\/ agent \u2014 \u0430\u0433\u0435\u043d\u0442 \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043e \u043f\u043e\u0433\u043e\u0434\u0435}\/\/ newLLMRoutes \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 \u0432\u0441\u0435 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u044b \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 LLM.func newLLMRoutes(api fiber.Router, l *slog.Logger, agent *agent.WeatherAgent) {\/\/ \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0441 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044f\u043c\u0438lr := llmRoutes{l, agent}\/\/ \u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043aapi.Post(weatherProcessRoute, lr.ProcessWeather)}\/\/ ProcessWeather \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441 \u043e \u043f\u0440\u043e\u0433\u043d\u043e\u0437\u0435 \u043f\u043e\u0433\u043e\u0434\u044b.func (lr *llmRoutes) ProcessWeather(c fiber.Ctx) error {\/\/ \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0441 \u0442\u0430\u0439\u043c\u0430\u0443\u0442\u043e\u043c 60 \u0441\u0435\u043a\u0443\u043d\u0434 \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0433\u043d\u043e\u0437\u0430ctx, cancel := context.WithTimeout(c.Context(), 60*time.Second)defer cancel()\/\/ \u041f\u0430\u0440\u0441\u0438\u043c JSON \u0438\u0437 \u0442\u0435\u043b\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0432 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 AgentRequestvar req AgentRequestraw := c.BodyRaw()if err := json.Unmarshal(raw, &amp;req); err != nil {\/\/ \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c HTTP 400 \u043f\u0440\u0438 \u043d\u0435\u0432\u0430\u043b\u0438\u0434\u043d\u043e\u043c JSONreturn c.Status(http.StatusBadRequest).JSON(fiber.Map{&#171;success&#187;: false,&#187;error&#187;:   &#171;\u041d\u0435\u0432\u0430\u043b\u0438\u0434\u043d\u044b\u0439 JSON&#187;,})}\/\/ \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e \u043f\u043e\u043b\u0435 prompt \u043d\u0435 \u043f\u0443\u0441\u0442\u043e\u0435if req.Prompt == &#171;&#187; {return c.Status(http.StatusBadRequest).JSON(fiber.Map{&#171;success&#187;: false,&#187;error&#187;:   &#171;\u041f\u043e\u043b\u0435 &#8216;prompt&#8217; \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e&#187;,})}\/\/ \u041b\u043e\u0433\u0438\u0440\u0443\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u043e \u043f\u043e\u0433\u043e\u0434\u0435 \u0441 \u0434\u043b\u0438\u043d\u043e\u0439 \u043f\u0440\u043e\u043c\u043f\u0442\u0430lr.l.Info(&#171;[ProcessWeather] Processing weather request&#187;, &#171;prompt_length&#187;, len(req.Prompt))\/\/ \u041f\u0435\u0440\u0435\u0434\u0430\u0451\u043c \u0437\u0430\u043f\u0440\u043e\u0441 \u0430\u0433\u0435\u043d\u0442\u0443 \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438response, err := lr.agent.ProcessWeather(ctx, req.Prompt)if err != nil {\/\/ \u041b\u043e\u0433\u0438\u0440\u0443\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0443 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438lr.l.Error(&#171;[ProcessWeather] Agent execution failed&#187;, &#171;error&#187;, err)\/\/ \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c HTTP 500 \u0441 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0438return c.Status(http.StatusInternalServerError).JSON(fiber.Map{&#171;success&#187;: false,&#187;error&#187;:   &#171;\u041e\u0448\u0438\u0431\u043a\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0430: &#187; + err.Error(),})}\/\/ \u041b\u043e\u0433\u0438\u0440\u0443\u0435\u043c \u0443\u0441\u043f\u0435\u0448\u043d\u0443\u044e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0441 \u0434\u043b\u0438\u043d\u043e\u0439 \u043e\u0442\u0432\u0435\u0442\u0430lr.l.Info(&#171;[ProcessWeather] Success&#187;, &#171;response_length&#187;, len(response))\/\/ \u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u043e\u0442\u0432\u0435\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0443return c.Status(http.StatusOK).JSON(fiber.Map{&#171;success&#187;:  true,&#187;response&#187;: response,&#187;message&#187;:  &#171;\u0417\u0430\u043f\u0440\u043e\u0441 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d&#187;,})}4.3. \u0428\u0430\u0433 3: \u0410\u0433\u0435\u043d\u0442 (agent\/weather_agent.go)\u0424\u0430\u0439\u043b: agent\/weather_agent.go\/\/ \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0434\u043b\u044f \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.type Logger interface {Debug(msg string, args &#8230;any)Info(msg string, args &#8230;any)Warn(msg string, args &#8230;any)Error(msg string, args &#8230;any)}\/\/ \u043e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0430\u0433\u0435\u043d\u0442\u0430 \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043e \u043f\u043e\u0433\u043e\u0434\u0435.type WeatherAgent struct {llm    llms.Model                   \/\/ \u044f\u0437\u044b\u043a\u043e\u0432\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044ctool   *weather.WeatherForecastTool \/\/ \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0430\u0433\u0435\u043d\u0442\u0430logger Logger                       \/\/ \u043b\u043e\u0433\u0433\u0435\u0440}\/\/ NewWeatherAgent \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442 \u043d\u043e\u0432\u044b\u0439 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 WeatherAgent.func NewWeatherAgent(llm llms.Model, l Logger) *WeatherAgent {l.Info(&#171;[WeatherAgent] Agent initialized&#187;)weatherTool := weather.NewWeatherForecastTool()return &amp;WeatherAgent{llm:    llm,tool:   weatherTool,logger: l,}}\/\/ ProcessWeather \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441 \u043e \u043f\u0440\u043e\u0433\u043d\u043e\u0437\u0435 \u043f\u043e\u0433\u043e\u0434\u044b.func (wa *WeatherAgent) ProcessWeather(ctx context.Context, input string) (string, error) {wa.logger.Info(&#171;[WeatherAgent] Starting weather processing&#187;, &#171;input_preview&#187;, input)\/\/ \u043e\u0442\u0434\u0430\u0435\u043c \u043d\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043f\u0440\u043e\u043c\u0442\u0430 \u0446\u0435\u043f\u043e\u0447\u043a\u043e\u0439 \u0430\u0433\u0435\u043d\u0442\u0430result, err := weather.HandleWeatherRequest(ctx, wa.llm, wa.tool, wa.logger, input)if err != nil {wa.logger.Error(&#171;[WeatherAgent] Weather processing failed&#187;, &#171;error&#187;, err)return &#171;&#187;, err}wa.logger.Info(&#171;[WeatherAgent] Weather processing completed successfully&#187;)return result, nil}4.4. \u0428\u0430\u0433 4: \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043f\u043e\u0433\u043e\u0434\u044b (weather\/handler.go)\u0424\u0430\u0439\u043b: weather\/handler.gofunc HandleWeatherRequest(ctx context.Context, llm llms.Model, tool *WeatherForecastTool, l Logger, userInput string) (string, error) {\/\/ \u041b\u043e\u0433\u0438\u0440\u0443\u0435\u043c \u043d\u0430\u0447\u0430\u043b\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043f\u043e\u0433\u043e\u0434\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430l.Info(&#171;[WeatherHandler] Starting weather forecast chain&#187;, &#171;input&#187;, userInput)\/\/ \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u0446\u0435\u043f\u043e\u0447\u043a\u0438 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u044d\u0442\u0430\u043f\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438\/\/ createExtractArgsChain \u2014 \u0438\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u0442 \u0433\u043e\u0440\u043e\u0434 \u0438 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0434\u043d\u0435\u0439 \u0438\u0437 \u0437\u0430\u043f\u0440\u043e\u0441\u0430extractChain := createExtractArgsChain(llm, l)\/\/ createParseArgsChain \u2014 \u043f\u0430\u0440\u0441\u0438\u0442 JSON \u0441 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u0432 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443parseArgsChain := createParseArgsChain(l)\/\/ createWeatherToolChain \u2014 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u043f\u043e\u0433\u043e\u0434\u044b \u0441 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u043c\u0438 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430\u043c\u0438weatherToolChain := createWeatherToolChain(tool, l)\/\/ createFinalResponseChain \u2014 \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u0443\u0435\u0442 \u0444\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u043e\u0442\u0432\u0435\u0442 \u0441 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u044f\u043c\u0438finalResponseChain := createFinalResponseChain(llm)\/\/ \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u0446\u0435\u043f\u043e\u0447\u043a\u0443 \u0438\u0437 \u0432\u0441\u0435\u0445 \u044d\u0442\u0430\u043f\u043e\u0432accumulatingChain := NewAccumulatingSequentialChain([]chains.Chain{extractChain,parseArgsChain,weatherToolChain,finalResponseChain,})l.Info(&#171;[WeatherHandler] AccumulatingSequentialChain created, executing&#8230;&#187;)\/\/ \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0446\u0435\u043f\u043e\u0447\u043a\u0443 \u0441 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u043cresult, err := accumulatingChain.Call(ctx, map[string]any{&#171;userInput&#187;: userInput,})if err != nil {\/\/ \u041b\u043e\u0433\u0438\u0440\u0443\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0443 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0446\u0435\u043f\u043e\u0447\u043a\u0438l.Error(&#171;[WeatherHandler] AccumulatingSequentialChain execution failed&#187;, &#171;error&#187;, err)return &#171;&#187;, err}\/\/ \u0418\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u043c \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0438\u0437 \u0432\u044b\u0445\u043e\u0434\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445finalOutput, ok := result[&#171;text&#187;].(string)if !ok {\/\/ \u041b\u043e\u0433\u0438\u0440\u0443\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0443 \u0442\u0438\u043f\u0430 \u0434\u0430\u043d\u043d\u044b\u0445l.Error(&#171;[WeatherHandler] Invalid output type from AccumulatingSequentialChain&#187;)return &#171;&#187;, fmt.Errorf(&#171;invalid output from AccumulatingSequentialChain&#187;)}\/\/ \u041b\u043e\u0433\u0438\u0440\u0443\u0435\u043c \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0435l.Info(&#171;[WeatherHandler] AccumulatingSequentialChain completed successfully&#187;)return finalOutput, nil}4.5. \u0428\u0430\u0433 5: \u0426\u0435\u043f\u043e\u0447\u043a\u0430 1 \u2014 ExtractArgsChain\u0417\u0430\u0434\u0430\u0447\u0430: \u0418\u0437\u0432\u043b\u0435\u0447\u044c \u0433\u043e\u0440\u043e\u0434 \u0438 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0434\u043d\u0435\u0439 \u0438\u0437 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430.\u0417\u0434\u0435\u0441\u044c \u0438 \u0434\u0430\u043b\u0435\u0435 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0448\u0430\u0431\u043b\u043e\u043d\u044b, \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u0438\u0438 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0438 \u0441\u043e\u0437\u0434\u0430\u044e\u0442\u0441\u044f \u043d\u0430\u0448\u0438 \u043f\u0440\u043e\u043c\u043f\u0442\u044b \u043a \u043c\u043e\u0434\u0435\u043b\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044f \u0432 \u043d\u0438\u0445 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043d\u0430\u043c \u0434\u0430\u043d\u043d\u044b\u0435\u0424\u0430\u0439\u043b: weather\/template.govar (\/\/ WeatherPromptTemplate \u2014 \u0448\u0430\u0431\u043b\u043e\u043d \u0434\u043b\u044f \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u044f \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0438\u0437 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.WeatherPromptTemplate prompts.PromptTemplate\/\/ FinalWeatherPromptTemplate \u2014&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-479305","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/479305","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=479305"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/479305\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=479305"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=479305"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=479305"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}