Last year, Začal jsem trochu hýčkatkolemZávěsná 4JJedná se o rychle rostoucí projekt a chtěl jsem se seznámit s aktualizacemi.Chtěl jsem také zkontrolovat, jak integrovat server Model Context Protocol v LangChain4J.
Verze 1 beta
Napsal jsem svůj poslední příspěvek v listopadu 2024 a použil jsem nejnovější verzi dostupnou v té době, 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. září 2024
0,35 Kč
22. prosince 2024
1.0.0-alfa1 a více
10. února 2025
Číslo 1.0-beta1
13. března 2025
Číslo 1.0-beta2
12. dubna 2025
Číslo 1.0-beta3
LangChain4J přicházíSemerováUdržovatelé využili příležitosti, aby zavedli změny, které přetrvávají.V mém případě jsem musel aktualizovat svůj kód, abych vypočítal změny API, které přetrvávají.
v0.35 |
v1.0.0-beta3 |
---|---|
val s = Sinks.many() |
val s = Sinks.many() |
Val s = Sinks.many()
Jednotlivé (
.onBackpressureBuffer<String>()
chatBot.talk (m.sessionId, m.text)
.onNásledující(s::tryEmitNásledující)
.onError(s::třebaEmitError)
neúplné
s.přesměrováníDokonalé()
Na začátek ( )
Připravte se na to, abyste se dostali na místo, kde se nacházíte. (
s.asFlux().asFlow()
)
Val s = Sinks.many()
Jednotlivé (
.onBackpressureBuffer<String>()
chatBot.talk (m.sessionId, m.text)
.onPoznávací odpověď(s::tryEmitNext)
.onError(s::třebaEmitError)
Kompletní odpověď {
s.přesměrováníDokonalé()
Na začátek ( )
Připravte se na to, abyste se dostali na místo, kde se nacházíte. (
s.asFlux().asFlow()
)
Projektová integrace reaktorů
LangChain4J nabízí integraci s projektovým reaktorem; chyběl mi v mých předchozích rozhovorech.a lot.
Já používámAiServices
, takže jsem dříve definoval rozhraní pro LangChain4J k implementaci v běhu:
interface ChatBot {
fun talk(@MemoryId sessionId: String, @UserMessage message: String): TokenStream
}
Měli bychom přidat následující závislost:
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-reactor</artifactId>
<version>1.0.0-beta3</version>
</dependency>
Nyní můžeme změnit typ vrácení zFlux<String>
Dvě ATokenStream
Zde je aktualizovaný podpis:
interface ChatBot {
fun talk(@MemoryId sessionId: String, @UserMessage message: String): Flux<String>
}
Tím se vytvářísink
Zjednodušit můžeme kód následovně:
val flux = chatBot.talk(m.sessionId, m.text)
ServerResponse.ok().bodyAndAwait(flux.asFlow())
Nezapomeňte, že dva dny debugování vám mohou snadno ušetřit dvě hodiny čtení dokumentace!
Integrace serveru s kontextovým protokolem
V této sekci chci do své aplikace LangChain4J integrovat <abbr title="Model Context Protocol">MCP</abbr>.
Retrieval rozšířené generace
Člověk potřebuje spoustu zdrojů, aby trénoval <abbr title="Large Language Model">LLM</abbr>: přímo se překládá do času a peněz. Z tohoto důvodu společnosti omezují školení nových verzí modelu. Relevance modelu se časem snižuje, protože informace se hromadí a mění, zatímco databáze LLM je neměnná.
Retrieval-Augmented Generation je dvoustupňový proces.V prvním kroku nástroj analyzuje data, vektorizuje je podle LLM a ukládá je do vektorové databáze; ve druhém, nástroj používá databázi jako další data při dotazování LLM.
Kontextový protokol
Nejnovějším způsobem, jak řešit statickou povahu LLM je MCP.
MCP je otevřený protokol, který standardizuje, jak aplikace poskytují kontext LLM. Přemýšlejte o MCP jako o portu USB-C pro aplikace AI. Stejně jako USB-C poskytuje standardizovaný způsob připojení vašich zařízení k různým periferiím a příslušenstvím, MCP poskytuje standardizovaný způsob připojení modelů AI k různým zdrojům dat a nástrojům.
Začněte s modelovým kontextovým protokolem
MCP je otevřený protokol, který standardizuje, jak aplikace poskytují kontext LLM. Přemýšlejte o MCP jako o portu USB-C pro aplikace AI. Stejně jako USB-C poskytuje standardizovaný způsob připojení vašich zařízení k různým periferiím a příslušenstvím, MCP poskytuje standardizovaný způsob připojení modelů AI k různým zdrojům dat a nástrojům.
Začněte s modelovým kontextovým protokolem
MCP má dvě výhody oproti 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 definujeDvě alternativy dopravypro komunikaci klient-server:
- stdio: Klient spouští podproces a komunikace probíhá nad standardem a standardem
- HTTP se serverovými událostmi
Architektura řešení
Po výše uvedené teorii jsme nyní připraveni na praktickou část. Začíná výběrem serveru MCP.zdeJe to dobrý začátek, ale já jsem si vybralOficiální server GitHub MCPProtože v dokumentaci LangChain4J se o tom zmiňuje.
GitHub MCP server nabízíStadiónTo znamená, že bychom měli získat binární a spustit ji z aplikace. Je to rychlé ve srovnání s HTTP transportem, ale vzhledem k celkovému času, který zahrnuje HTTP volání do modelu a výpočetní čas na jeho straně, je to irelevantní.
Po několika výzkumech jsem zjistil, žePříslušenství pro proxyProjekt. Umožňuje přepínat mezi buď ze stdio na HTTP nebo z HTTP na stdio. Je také k dispozici jako obrázek Docker. Můžeme kombinovat server i proxy s následujícími funkcemi: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
- Stáhněte si archiv
- extrahovat to
- Odstranit archiv
- Udělejte binární exekutivní
Všimněte si, že nelze definovatCMD
jako binární umožňuje pouze konfigurovat port a hostitel s parametry. z tohoto důvodu musíme odložit příkaz při běhu, nebo v mém případě vdocker-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
- Potřebujeme změnu prostředí GITHUB_PERSONAL_ACCESS_TOKEN s platným tokenem pro ověření na GitHub
- Přeneste všechny environmentální proměnné do podprocesu
- Nastavení portu pro poslech
- Připojte se k jakémukoliv IP
- Proxy "připojí" se k stdio MCP serveru po
- Spusťte server se všemi možnostmi zapnutými
Obrázek poskytne/sse
Připojení na port 8080.
Kódování řešení
Kódování je nejjednodušší část. Hlavu dolů naDokumentace LangChain4J na MCPa pokračujte dále.V projektu se překládá následovně:
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)
}
}
- Přidal jsem třídu ConfigurationProperty pro parametrizování URL SSE
- Protokol MCP poskytuje způsob, jak posílat protokoly zpět do klienta
- Není to nutné, ale pomohlo mi to zajistit, aby se klient připojil k serveru a mohl seznam nástrojů poskytnutých
- Plug v poskytovateli nástrojů MCP vytvořeném výše v AiServices
V tomto okamžiku by měl model předat žádost, která odpovídá některému z registrovaných nástrojů serveru MCP.
curl -N -H 'Content-Type: application/json' localhost:8080 -d '{ "sessionId": "1", "text": "What are my top three most popular GitHub repos?" }'
Zkoušela jsem to několikrát a dostala jsem odpovědi na tyto otázky:
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.
Model prostě ignoroval nástroje navzdory dokumentaci, která tvrdí opak.
Fixování řešení
Párkrát jsem četl dokumentaci LangChain4J, ale k ničemu. Snažil jsem se používat OpenAI a hrstku dalších nástrojů AI bez úspěchu. Většina odpovědí potvrdila, že by mělo fungovat mimo krabici. Někteří zmínili volání nástroje přímo, což porazí účel; jeden zmínil, že Ollama nepodporuje nástroje. Zkontroloval jsem blog Ollama: oznámil podporu nástrojů v roce 2024.
Rozpojená architektura zavádí více pohyblivých kusů. Podezřel jsem se, že v celém řetězci hovorů může být něco špatně. Odstranil jsem proxy MCP, přidalgithub-mcp-server
přímo na obraz aplikace a změnil kód z HTTP na stdio.
Byl jsem blízko k tomu, abych se vzdal, když jsem se rozhodl vrátit se ke kořenům.Vzorek z dokumentaceByl to můj ha-ha moment.
Vzorek používá OpenAI, zatímco já používám Ollama. Zkoušel jsem MCP s OpenAI, Mistral AI a Ollama. Pouze model OpenAI funguje s MCP. Poslal jsem stejnou žádost jako výše:
curl -N -H 'Content-Type: application/json' localhost:8080 -d '{ "sessionId": "1", "text": "What are my top three most popular GitHub repos?" }'
Nyní OpenAI správně mapuje požadavek na správný nástroj a vrací odpověď, kterou jsem očekával:
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.%
Protože předáváme token autentizace serveru MCP, který jej předává API GitHub, ten ví, který uživatel volá.my reposPřiznávám, že se jedná o neobvyklý případ použití pro běžné webové aplikace, které slouží více uživatelům, ale používají jeden identifikační token každý.
Další časté otázky,Jde o g., najít nejoblíbenější úložiště na GitHub, jsou relevantní pro webové aplikace, protože nemají implicitní kontext – uživatele.
Závěr
Hlavním zaměřením tohoto příspěvku je integrace serveru MCP do aplikace LangChain4J. Zatímco konfigurace je díky dokumentaci jednoduchá, existuje několik varování.
Za prvé, jak se server MCP vejde do vaší architektury, je stále na vás. Musel jsem být kreativní, abych ho odpojil, pomocí vynikajícímcp-proxy
Pak se zdá, že LangChain4J je úniková abstrakce. dělá vše možné, aby vám poskytla silnou abstrakční vrstvu, ale implementace pod ní vás chrání před nejsou stejné.
Dozvěděl jsem se o MCP v reálném světě, a to otevřelo docela několik dveří pro projektové nápady.
Kompletní zdrojový kód tohoto článku naleznete naGitHub.
To go further:
- Začněte s modelovým kontextovým protokolem
- Najít skvělé MCP servery a klienty
- LangChain4J - Modelový kontextový protokol (MCP)
Původně publikováno v A Java Geek dne 27. dubna 2025
Jak na Java Geek