Last year, Nagsimula ako ng isang bitTungkol saMga pahinang tumuturo sa 4JIto ay isang mabilis na bumuo na proyekto, at gusto kong malaman ang mga update. Gusto ko rin upang tingnan kung paano mag-integrate ng isang Model Context Protocol server sa LangChain4J.
Pagkakaiba sa Beta 1
Nagsulat ko ang aking unang post noong Nobyembre 2024 at ginagamit ang pinakabagong bersyon na magagamit sa oras, v0.35. LangChain4J nagsimula ang kanyang paglipas sa 1.0 noong Disyembre noong nakaraang taon.
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 |
Setyembre 25, 2024
ang 0.35
Disyembre 22, 2024
Mga pahinang tumuturo sa 1.0.1
Pebrero 10, 2025
Mga pahinang tumuturo sa Beta 1
Marso 13, 2025
Ang mga ito ay 1.0-beta2
Oktubre 12, 2025
I-download ang beta3
LangChain4J sa pamamagitan ngang simulaAng mga manunulat ay gumagamit ng pagkakataon upang i-introduce ang mga pagbabago ng breaking. Sa aking kaso, kailangan kong i-update ang aking code upang i-account ang mga pagbabago ng API.
v0.35 |
v1.0.0-beta3 |
---|---|
val s = Sinks.many() |
val s = Sinks.many() |
ang napili ng mga taga-hanga: Sinks.many()
Mga pahinang ito(
.onBackpressureBuffer<String>()
ang napili ng mga taga-hanga: chatBot.talk(m.sessionId, m.text)
ang napili ng mga taga-hanga: tryEmitNext
Mga pahinang tumuturo:
Ang mga kompleto
Mga pahinang tumuturo (
Ipasok ang Start()
Mga pahinang tumuturo (
Mga pahinang tumuturo (
)
ang napili ng mga taga-hanga: Sinks.many()
Mga pahinang ito(
.onBackpressureBuffer<String>()
ang napili ng mga taga-hanga: chatBot.talk(m.sessionId, m.text)
Mga pahinang tumuturo (s::tryEmitNext)
Mga pahinang tumuturo:
Ang mga sumusunod {
Mga pahinang tumuturo (
Ipasok ang Start()
Mga pahinang tumuturo (
Mga pahinang tumuturo (
)
Integrasyon ng Reactor
Ang LangChain4J ay nag-aalok ng isang Project Reactor integration; hindi ko na ito inilabas sa aking mga nakaraang musings. Sa Kotlin coroutines, ito ay simplising ang codea lot.
Ako ay gumagamitAiServices
, kaya inihahanda ko ang isang interface para sa LangChain4J upang i-implementate sa runtime:
interface ChatBot {
fun talk(@MemoryId sessionId: String, @UserMessage message: String): TokenStream
}
Kailangan natin ang mga sumusunod na dependency:
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-reactor</artifactId>
<version>1.0.0-beta3</version>
</dependency>
Ngayon, maaari naming i-change ang return type mula sa aFlux<String>
ang aTokenStream
Narito ang updated signature:
interface ChatBot {
fun talk(@MemoryId sessionId: String, @UserMessage message: String): Flux<String>
}
Ito ay nagtataguyod ng mgasink
May mga bagay na kailangan nating i-simplify ang code na ito:
val flux = chatBot.talk(m.sessionId, m.text)
ServerResponse.ok().bodyAndAwait(flux.asFlow())
Pumunta na ang dalawang araw ng mga debugging ay maaaring madaling i-save mo ang dalawang oras ng pag-read ng dokumentasyon!
Paggamit ng isang Context Protocol Server
Sa seksyon na ito, gusto kong mag-integrate ng isang <abbr title="Model Context Protocol">MCP</abbr> sa aking LangChain4J application.
Pagbabago ng Generation
Kailangan ng maraming mga resource upang i-train ang isang <abbr title="Large Language Model">LLM</abbr>: ito ay direktang i-translate sa oras at pera. Para sa mga dahilan na ito, ang mga kumpanya ay limitado ang pagsasanay ng mga bagong mga bersyon ng modelo. Ang relevansiya ng isang modelo ay humaba sa panahon bilang impormasyon kumonekta at pagbabago, habang ang database ng LLM ay walang pagbabago. Higit pa, ang LLM ay i-trained sa mga publikong data-pagkailangang, habang ang karamihan ng mga kumpanya ay nais upang i-question ang kanilang mga private data din.
Ang Retrieval-Augmented Generation ay isang dalawang-step na proseso. Sa unang pagkakataon, ang tool ay pag-analisa ng data, vectorize ito ayon sa LLM, at i-save ito sa isang vector database; sa ikalawang, ang tool ay gumagamit ang database bilang mga pangunahing data kapag pag-interrogate sa LLM.
Ang kontekstong protocol
Ang pinakamataas na paraan upang matugunan ang static nature ng LLMs ay MCP.
Ang MCP ay isang open protocol na nag-standardize kung paano ang mga application ay nagbibigay ng kontekstong sa LLMs. Pag-iisip ng MCP tulad ng isang port ng USB-C para sa mga application ng AI. Tulad ng USB-C ay nagbibigay ng isang standardized paraan upang i-connect ang iyong mga device sa iba't ibang mga peripherals at accessories, ang MCP ay nagbibigay ng isang standardized paraan upang i-connect ang mga modelo ng AI sa iba't ibang mga source ng data at mga tool.
-- Buksan ang Model Context Protocol
Ang MCP ay isang open protocol na nag-standardize kung paano ang mga application ay nagbibigay ng kontekstong sa LLMs. Pag-iisip ng MCP tulad ng isang port ng USB-C para sa mga application ng AI. Tulad ng USB-C ay nagbibigay ng isang standardized paraan upang i-connect ang iyong mga device sa iba't ibang mga peripherals at accessories, ang MCP ay nagbibigay ng isang standardized paraan upang i-connect ang mga modelo ng AI sa iba't ibang mga source ng data at mga tool.
- angMagsisimula ang Model Context Protocol
Ang MCP ay may dalawang halaga sa 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!
Mga definisyon ng MCPtwo transport alternativesPara sa Client-Server Communications:
- stdio: Ang client ay nagsisimula ng isang subprocess, at ang komunikasyon ay dumating sa pamamagitan ng standard in at standard out
- HTTP sa Server-Sent Events
Arkitektura ng solusyon
Pagkatapos ng mga teorya sa itaas, kami ngayon ay handa para sa mga hands-on bahagi. Ito ay nagsisimula sa pamamagitan ng piliin ng isang MCP server.ditoIto ay isang mahusay na lugar upang magsimula, ngunit ito ay angMga pahinang tumuturo sa GitHub MCP Serverdahil ang dokumento ng LangChain4J ay nagsasalita ito.
Ang GitHub MCP server ay nagbibigay ngang studiotransportasyon. Ito ay nangangahulugan na kailangan nating makakuha ng binary at magsimula ito mula sa application. Ito ay mabilis kaysa sa HTTP transportasyon, ngunit dahil sa kabuuang oras na binubuo ng HTTP call sa modelo at ang oras ng pag-calculate sa kanyang pahina, ito ay hindi karaniwang. mula sa punto ng arkitektura, gusto ko ng isang dedicated component na may kanyang proseso.
Pagkatapos ng ilang mga pananaliksik, nakita ko angMga ProxyProject. Ito ay nagbibigay-daan sa iyo upang i-switch mula sa stdio sa HTTP o mula sa HTTP sa stdio. Ito ay magagamit din bilang isang Docker na imahe. Maaari naming mag-kombinasyon ang parehong server at proxy sa mga sumusunod naDockerfile
:
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
- I-download ang archive
- I-extract ang
- Pumunta ang archive
- Gawin ang Binary Executable
Tingnan mo na hindi ko alam ang definisyonCMD
dahil ang binary lamang ay nagbibigay-daan upang i-configure ang port at ang host na may mga parameter. Dahil dito, kailangan naming i-post ang command sa runtime, o sa aking kaso, sadocker-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
- Kailangan namin ng isang GITHUB_PERSONAL_ACCESS_TOKEN environment variable na may isang valid na token upang authenticate sa GitHub
- Ipasok ang lahat ng mga environment variables sa subprocess
- I-set ang listening port
- Pumunta sa anumang IP
- Ang proxy "connects" sa stdio MCP server pagkatapos ng dash
- I-run ang server na may lahat ng mga pagpipilian na i-enabled
Ang imahe ay magbibigay ng/sse
Ipinanganak ang port 8080.
Pag-coding ang solusyon
Ang pag-coding bahagi ay ang mas madaling. Head down to theLangChain4J dokumentasyon sa MCPat patuloy. Sa proyekto, ito ay inilathala bilang ang sumusunod:
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)
}
}
- Ipinapakita ko ang isang klase ng ConfigurationProperty upang parameterize ang SSE URL
- Ang MCP protocol ay nagbibigay ng isang paraan upang magpadala ng mga logback sa client
- Hindi kinakailangan, ngunit itinuturing ko na sigurado na ang client ay naka-connected sa server at maaaring listahan ang mga tool na ibinigay
- Plug in the MCP tool provider created above in the
AiServices
Sa oras na ito, ang modelo ay dapat ipadala ng isang request na matatagpuan sa anumang mga registrated tool sa MCP server.
curl -N -H 'Content-Type: application/json' localhost:8080 -d '{ "sessionId": "1", "text": "What are my top three most popular GitHub repos?" }'
Nagsimula ako ng ilang beses, at nakuha ko ang mga solusyon sa mga ito:
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.
Ang modelo lamang nangangahulugan ang mga tool maliban sa mga dokumento na nag-aalok ng iba't ibang.
I-fix ang solusyon
I read the LangChain4J documentation a few times, but to no avail. I tried to use OpenAI and a handful of other AI tools with no success. Karamihan ng mga solusyon confirmed it should work out of the box. Some mentioned calling the tool directly, which defeats the purpose; one mentioned that Ollama didn't support tools. I checked the Ollama blog: it announced tools' support in 2024. I've been stuck for a day, nag-iisip na kung ano ang ginawa ko malaki.
Ang disconnected architecture ay nagpapahiwatig ng higit pa na-move pieces. I suspected something might be wrong in the entire call chain. I removed the MCP proxy, idinagdag anggithub-mcp-server
Direct sa application image, at i-changed ang code mula sa HTTP sa stdio.
I was about to give up when I decided to come back to the roots. sa loob ng isang taon na ang nakalipassample mula sa documentation: ito ay just worked! Ito ay ang aking ha-ha moment.
Ang sample ay gumagamit ng OpenAI, habang ako ay gumagamit ng Ollama. I tried MCP sa OpenAI, Mistral AI, at Ollama. Only ang OpenAI model ay gumagana sa MCP. I sent the same request as above:
curl -N -H 'Content-Type: application/json' localhost:8080 -d '{ "sessionId": "1", "text": "What are my top three most popular GitHub repos?" }'
Ngayon, OpenAI correctly mapes ang request sa correct tool at ibalik ang solusyon na inaasahan ko:
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.%
Dahil nagpasya namin ang isang token ng authentication sa server ng MCP, na nagpasya ito sa GitHub API, ang latter ay alam kung ano ang gumagamit na gumagawa ng pag-call.my reposIto ay isang unusual na kaso ng paggamit para sa regular na mga web application na nagtatrabaho sa maraming mga gumagamit, ngunit gamitin ang isang single authentication token bawat.
Mga regular na mga tanong,ang g., makikita ang mga pinaka-popular na repositories sa GitHub, ay karaniwang para sa mga web application, dahil hindi nila may implisitong konteksto - ang user.
Konklusyon
Ang pangunahing fokus ng post na ito ay ang integrasyon ng isang server ng MCP sa isang LangChain4J app. Habang ang konfigurasyon ay simpleng sa pamamagitan ng dokumento, mayroong ilang mga cautions.
Sa isang panayam sa Star for All Seasons, sinabi niyang something new for her ang karakter na gagampanan niya.mcp-proxy
Pagkatapos, LangChain4J ay nagpapakita na maging isang leaky abstraction. Ito ay gumagawa ng lahat ng posible upang magbigay sa iyo ng isang malakas na layer ng abstraction, ngunit ang mga implementasyon sa ilalim ng ito shields sa iyo mula ay hindi katumbas.
Alam ko tungkol sa MCP sa real world, at ito ay bumuo ng maraming mga door para sa mga ideya ng proyekto.
Ang buong source code para sa post na ito ay makikita saang github.
To go further:
- Magsisimula ang Model Context Protocol
- Maghanap ng Awesome MCP Servers at Clients
- LangChain4J - Modelo ng Context Protocol (MCP)
Nai-publish sa A Java Geek sa Abril 27, 2025
Ang isang Java Geek