Минатата година,Почнав да се мачкам малкуоколуСеријал 4JТоа е брзо растечки проект, и сакав да се запознаам со надградбите. исто така, сакав да проверам како да се интегрира сервер за протокол за контекст на модел во LangChain4J.
Бета верзија 1
Јас го напишав мојот последен пост во ноември 2024 година и ја користев најновата верзија достапна во тоа време, v0.35.
Date |
Release |
---|---|
September 25th, 2024 |
0.35.0 |
December 22th, 2024 |
1.0.0-alpha1 |
February 10th, 2025 |
1.0.0-beta1 |
March 13th, 2025 |
1.0.0-beta2 |
April 12th, 2025 |
1.0.0-beta3 |
25 септември 2024
35.0 од
22 декември 2024
1.4 Алфа 1
10 февруари, 2025
1.1 Бета 1
13 март, 2025
1.1 Бета 2
12 април, 2025
1.1 Бета 3
LangChain4J следиСемејВо мојот случај, морав да го ажурирам мојот код за да одговорам на промените во API.
v0.35 |
v1.0.0-beta3 |
---|---|
val s = Sinks.many() |
val s = Sinks.many() |
Вредноста на S = Sinks.many()
Ѓорѓиќ (
.onBackpressureБуфер <String>()
chatBot.talk(m.sessionId, m.text) на сајтот
.onNext(s::tryEmitNext) на веб-страницата
.onError(s::tryЕмитувањеError)
Не е комплетно
Заврши со работа(
Почеток на настанот (
Потврда за прекршување на прекршување на прекршување (
Соодветно на фактот дека (
)
Вредноста на S = Sinks.many()
Ѓорѓиќ (
.onBackpressureБуфер <String>()
chatBot.talk(m.sessionId, m.text) на сајтот
Одговор на прашањето(s::tryEmitNext)
.onError(s::tryЕмитувањеError)
.onCompleteодговор {
Заврши со работа(
Почеток на настанот (
Потврда за прекршување на прекршување на прекршување (
Соодветно на фактот дека (
)
Интеграција на проектни реактори
LangChain4J нуди интеграција на Project Reactor; го пропуштив во моите претходни размислувања.a lot.
Јас користамAiServices
, така што претходно го дефинирав интерфејсот за LangChain4J да се имплементира во време на извршување:
interface ChatBot {
fun talk(@MemoryId sessionId: String, @UserMessage message: String): TokenStream
}
Треба да се додаде следната зависност:
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-reactor</artifactId>
<version>1.0.0-beta3</version>
</dependency>
Сега можеме да го смениме типот на враќање одFlux<String>
Две аTokenStream
Еве го ажурираниот потпис:
interface ChatBot {
fun talk(@MemoryId sessionId: String, @UserMessage message: String): Flux<String>
}
Тоа го прави создавањето наsink
Подолу не е потребно.Можеме да го поедноставиме кодот како што следува:
val flux = chatBot.talk(m.sessionId, m.text)
ServerResponse.ok().bodyAndAwait(flux.asFlow())
Запомнете дека два дена дебагирање лесно може да ви заштеди два часа на читање на документацијата!
Интегрирање на модел на протокол сервер
Во овој дел, сакам да интегрирам <abbr title="Model Context Protocol">MCP</abbr> во мојата LangChain4J апликација.
Повторно зголемена генерација
Потребни се многу ресурси за да се обучи <abbr title="Large Language Model">LLM</abbr>: тоа директно се преведува во време и пари. Поради оваа причина, компаниите го ограничуваат обуката на нови верзии на моделот. Релевантноста на моделот се намалува со текот на времето како информациите се акумулира и се менува, додека базата на податоци на LLM е непроменлива. Покрај тоа, LLMs се обучени на јавни податоци-по природа, додека повеќето компании сакаат да ги прашаат своите приватни податоци исто така.
Во првиот чекор, алатката ги анализира податоците, ги векторизира според LLM и ги складира во векторска база на податоци; во вториот, алатката ја користи базата на податоци како дополнителни податоци при барање на LLM.
Модерен контекст протокол
Најновиот начин да се справи со статичката природа на LLMs е MCP.
MCP е отворен протокол кој стандардизира како апликациите обезбедуваат контекст за LLMs. Размислете за MCP како USB-C порт за апликации за AI. Исто како што USB-C обезбедува стандардизиран начин за поврзување на вашите уреди со различни периферии и додатоци, MCP обезбедува стандардизиран начин за поврзување на моделите на AI со различни извори на податоци и алатки.
Започнете со протоколот Модел контекст
MCP е отворен протокол кој стандардизира како апликациите обезбедуваат контекст за LLMs. Размислете за MCP како USB-C порт за апликации за AI. Исто како што USB-C обезбедува стандардизиран начин за поврзување на вашите уреди со различни периферии и додатоци, MCP обезбедува стандардизиран начин за поврзување на моделите на AI со различни извори на податоци и алатки.
- наЗапочнете со протокол за контекст на моделот
MCP има две предности во однос на RAG:
-
Data processed by a RAG is tailored for a model. If one wants to use a new model, one must re-execute the parsing phase. MCP standardizes the interactions between a client and a server, making them technology-independent.
-
RAG allows the reading of data. MCP allows any API call to either access data dynamically or execute actions!
MCP дефинира2 Алтернативни начини на транспортЗа комуникација клиент-сервер:
- stdio: Клиентот лансира подпроцес, а комуникацијата се случува преку стандард во и стандард надвор
- HTTP со настани за испраќање на сервери
Архитектура на решението
По горенаведената теорија, сега сме подготвени за практичниот дел. Тоа започнува со изборот на MCP сервер.Овде's a good starting point. However, I chose the Официјален GitHub MCP сервербидејќи документацијата LangChain4J го споменува тоа.
GitHub MCP серверот нудиСтадионотТоа значи дека треба да го добиеме бинарниот и да го започнеме од апликацијата. Тоа е брзо во споредба со HTTP транспортот, но со оглед на вкупното време кое го сочинува HTTP повикот на моделот и времето за пресметување на неговата страна, тоа е ирелевантно.
По некои истражувања, најдовмеMCP-прокси софтверПроектот. Тоа ви овозможува да се префрлите помеѓу или од студио на HTTP или од HTTP на студио. Исто така е достапен како слика Docker. Можеме да ги комбинираме и серверот и прокси со следновоDockerfile
:
FROM ghcr.io/sparfenyuk/mcp-proxy:latest
ENV VERSION=0.2.0
ENV ARCHIVE_NAME=github-mcp-server_Linux_x86_64.tar.gz
RUN wget https://github.com/github/github-mcp-server/releases/download/v$VERSION/$ARCHIVE_NAME -O /tmp/$ARCHIVE_NAME \ #1
&& tar -xzvf /tmp/$ARCHIVE_NAME -C /opt \ #2
&& rm /tmp/$ARCHIVE_NAME #3
RUN chmod +x /opt/github-mcp-server #4
- Преземете го архивот
- Извадете го
- Избришете го архивот
- Направете ги бинарните извршни
Забележете дека не можеме да го дефинирамеCMD
како што бинарниот дозволува само конфигурирање на портот и домаќинот со параметри. Поради оваа причина, мораме да ја одложиме командата на време на извршување, или во мојот случај, воdocker-compose.yaml
:
services:
mcp-server:
build:
context: github-mcp-server
env_file:
- .env #1
command:
- --pass-environment #2
- --sse-port=8080 #3
- --sse-host=0.0.0.0 #4
- -- #5
- /opt/github-mcp-server #6
- --toolsets
- all
- stdio
- Потребна ни е променлива на GITHUB_PERSONAL_ACCESS_TOKEN животната средина со валиден токен за да се автентифицира на GitHub
- Пренесете ги сите променливи на животната средина во подпроцесот
- Поставете пристаниште за слушање
- Поврзете се на било кој IP
- Проксиот "се поврзува" со MCP серверот на студиото по дашот
- Извршете го серверот со сите опции
Сликата ќе обезбеди/sse
Поврзување на портот 8080
Кодирање на решението
Кодирањето е најлесниот дел.LangChain4J документација за MCPи следете понатаму. Во проектот, тоа се преведува како што следува:
bean {
val transport = HttpMcpTransport.Builder()
.sseUrl(ref<ApplicationProperties>().mcp.url) //1
.logRequests(true) //2
.logResponses(true) //2
.build()
val mcpClient = DefaultMcpClient.Builder()
.transport(transport)
.build()
mcpClient.listTools().forEach { println(it) } //3
McpToolProvider.builder()
.mcpClients(listOf(mcpClient))
.build()
}
bean {
coRouter {
val chatBot = AiServices
.builder(ChatBot::class.java)
.streamingChatLanguageModel(ref<StreamingChatLanguageModel>())
.chatMemoryProvider { MessageWindowChatMemory.withMaxMessages(40) }
.contentRetriever(EmbeddingStoreContentRetriever.from(ref<EmbeddingStore<TextSegment>>()))
.toolProvider(ref<McpToolProvider>()) //4
.build()
POST("/")(PromptHandler(chatBot)::handle)
}
}
- Додадов класа ConfigurationProperty за параметризирање на URL-то на SSE
- MCP протоколот обезбедува начин за испраќање на logs назад до клиентот
- Не е неопходно, но ми помогна да се осигурам дека клиентот е поврзан со серверот и може да ги наведе алатките обезбедени
- Вклучете го провајдерот на MCP алатки создаден погоре во AiServices
Во овој момент, моделот треба да испрати барање кое одговара на која било од регистрираните алатки до MCP серверот.
curl -N -H 'Content-Type: application/json' localhost:8080 -d '{ "sessionId": "1", "text": "What are my top three most popular GitHub repos?" }'
Се обидов неколку пати, и добив одговори во текот на овие линии:
Unfortunately, the provided text does not contain any information about your top three most popular GitHub repositories. The text appears to be a blog post or a personal website, and it mentions some of your projects and experiences with GitHub, but it does not provide any metrics or statistics on the popularity of your repositories.
If you want to know more about the popularity of your GitHub repositories, I would recommend checking out GitHub's own analytics tools, such as GitHub Insights or the Repository Insights API. These tools can provide information about the number of followers, stars, and forks for each repository, as well as other metrics like engagement and activity.
Моделот едноставно ги игнорираше алатките, и покрај документите кои тврдат спротивно.
Поставување на решението
Прочитав документацијата на LangChain4J неколку пати, но без никаква корист. Се обидов да користам OpenAI и неколку други алатки за вештачка интелигенција без успех. Повеќето од одговорите потврдија дека треба да работи надвор од кутијата. Некои споменаа директно повикување на алатката, што ја победува целта; еден спомена дека Оллама не ги поддржува алатките.
Раздвојувањето на архитектурата воведува повеќе движечки парчиња. Се сомневав дека нешто може да не е во ред во целиот синџир на повици.github-mcp-server
директно на сликата на апликацијата, и го промени кодот од HTTP на stdio.
Бев подготвен да се откажам кога решив да се вратам на корените.Пример од документацијатаТоа беше мојот ха-ха момент.
Примерот користи OpenAI, додека јас го користев Ollama. јас се обидов MCP со OpenAI, Mistral AI, и Ollama. Само OpenAI модел работи со MCP. Јас го испратив истото барање како погоре:
curl -N -H 'Content-Type: application/json' localhost:8080 -d '{ "sessionId": "1", "text": "What are my top three most popular GitHub repos?" }'
Сега, OpenAI правилно ја мапира барањето до вистинската алатка и го враќа одговорот што го очекував:
Here are my findings regarding your top three most popular GitHub repositories:
1. **[opentelemetry-tracing](https://github.com/nfrankel/opentelemetry-tracing)**
- **Description**: Demo for end-to-end tracing via OpenTelemetry.
- **Stars**: 68
- **Forks**: 25
- **Open Issues**: 10
2. **[kaadin](https://github.com/nfrankel/kaadin)**
- **Description**: Kotlin DSL for Vaadin.
- **Stars**: 44
- **Forks**: 12
- **Open Issues**: 3
3. **[jvm-controller](https://github.com/nfrankel/jvm-controller)**
- **Description**: Example on how to write a Kubernetes controller in Java.
- **Stars**: 33
- **Forks**: 10
- **Open Issues**: 0
These repositories demonstrate a range of your interests and contributions in the areas of observability, Kotlin development, and Kubernetes.%
Бидејќи го пренесуваме токенот за автентикација на MCP серверот, кој го пренесува на GitHub API, тој знае кој корисник го прави повикот.my reposПризнавам дека тоа е необичен случај на употреба за редовните веб апликации кои се однесуваат на повеќе корисници, но користат еден идентификациски токен секој.
Други редовни прашања,на Г.Најпопуларните репозитории на GitHub се релевантни за веб апликации, бидејќи немаат имплицитен контекст – корисникот.
Заклучок
Главниот фокус на оваа статија е интеграцијата на MCP серверот во апликацијата LangChain4J. Додека конфигурацијата е едноставна благодарение на документацијата, постојат неколку предупредувања.
Прво, како MCP серверот се вклопува во вашата архитектура е сè уште до вас. морав да бидам креативен за да го одвојам, користејќи го одличниотmcp-proxy
Потоа, LangChain4J се чини дека е течна апстракција. Тој прави сè што е можно за да ви обезбеди силен слој на апстракција, но имплементациите под него ве штити од не се еднакви.
Научив за MCP во реалниот свет, и тоа отвори неколку врати за проект идеи.
Целосниот изворниот код за оваа статија може да се најде наGitHub.
To go further:
- Започнете со протокол за контекст на моделот
- Find Awesome MCP Servers and Clients
- LangChain4J - Протокол за моделен контекст (MCP)
Првично објавено на A Java Geek на 27 април, 2025
Јава гејк