Új történelem

LangChain4J 6 hónappal később

által Nicolas Fränkel11m2025/05/01
Read on Terminal Reader

Túl hosszú; Olvasni

Ennek a bejegyzésnek a középpontjában az MCP-kiszolgáló integrációja áll egy LangChain4J alkalmazásban.A konfiguráció a dokumentációnak köszönhetően egyszerű, de van néhány figyelmeztetés.
featured image - LangChain4J 6 hónappal később
Nicolas Fränkel HackerNoon profile picture

A tavalyi évben,Elkezdtem egy kicsitKörülSzékesfehérvár4JEz egy gyorsan növekvő projekt, és meg akartam ismerkedni a frissítésekkel. Azt is meg akartam nézni, hogyan lehet integrálni egy Model Context Protocol szervert a LangChain4J-be.

1 Béta verzió

Az utolsó bejegyzésemet 2024 novemberében írtam, és az akkor elérhető legújabb verziót használtam, a v0.35. LangChain4J tavaly decemberben kezdte meg az 1.0 felé vezető utat.

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

szeptember 25, 2024

0 0 0 0

december 22, 2024

1 alfa1 alfa1

február 10, 2025

1 Béta1 Béta1

Március 13, 2025

1 Béta2 Béta2

Április 12, 2025

1.10 Béta3


LangChain4J előzetesSzemfényA karbantartók kihasználták az alkalmat, hogy bevezessék a megszakító változásokat. Az én esetemben frissítenem kellett a kódomat az API megszakító változásainak figyelembevétele érdekében.

v0.35

v1.0.0-beta3

val s = Sinks.many()
.unicast()
.onBackpressureBuffer<String>()
chatBot.talk(m.sessionId, m.text)
.onNext(s::tryEmitNext)
.onError(s::tryEmitError)
.onComplete {
s.tryEmitComplete()
}.start()
return ServerResponse.ok().bodyAndAwait(
s.asFlux().asFlow()
)

val s = Sinks.many()
.unicast()
.onBackpressureBuffer<String>()
chatBot.talk(m.sessionId, m.text)
.onPartialResponse(s::tryEmitNext)
.onError(s::tryEmitError)
.onCompleteResponse {
s.tryEmitComplete()
}.start()
return ServerResponse.ok().bodyAndAwait(
s.asFlux().asFlow()
)

Val s = szűk. sok()
Egyedülálló (
.onBackpressureBuffer<String>()
chatBot.talk(m.sessionId, m.text) - A beszélgetés
.on Következő(s::tryEmitNext)
.onHiba(s::nyomtatásHiba)
A teljes
Teljes körű(
Kezdőlap »
Hasonlóképpen, ha a hűtőszekrény (
Azaz a(z) a(z) a(z)
)

Val s = szűk. sok()
Egyedülálló (
.onBackpressureBuffer<String>()
chatBot.talk(m.sessionId, m.text) - A beszélgetés
KezdőlapHírekHírek(s::tryEmitNext)
.onHiba(s::nyomtatásHiba)
.onTeljes válasz {
Teljes körű(
Kezdőlap »
Hasonlóképpen, ha a hűtőszekrény (
Azaz a(z) a(z) a(z)
)

Reaktor integráció

A LangChain4J a Project Reactor integrációját kínálja; az előző gondolataimban hiányoztam.a lot.

Én használomAiServices, így korábban meghatároztam egy felületet a LangChain4J számára, hogy végrehajtsa a futási időben:


interface ChatBot {
    fun talk(@MemoryId sessionId: String, @UserMessage message: String): TokenStream
}


Ehhez a következő függőséget kell kialakítanunk:


<dependency>
    <groupId>dev.langchain4j</groupId>
    <artifactId>langchain4j-reactor</artifactId>
    <version>1.0.0-beta3</version>
</dependency>


Most már megváltoztathatjuk a visszatérés típusát aFlux<String>A kétTokenStreamÍme a frissített aláírás:


interface ChatBot {
    fun talk(@MemoryId sessionId: String, @UserMessage message: String): Flux<String>
}


Ez teszi lehetővé a létrehozását asinkA fentiek nem szükségesek. a kódot a következőképpen egyszerűsíthetjük:


val flux = chatBot.talk(m.sessionId, m.text)
ServerResponse.ok().bodyAndAwait(flux.asFlow())


Ne feledje, hogy két napos hibakeresés könnyen megtakaríthatja a dokumentáció olvasásának két óráját!

Kontextusprotokoll szerver integrálása

Ebben a szakaszban szeretnék integrálni egy <abbr title="Model Context Protocol">MCP</abbr> a LangChain4J alkalmazásomban.

Megnövekedett generáció

Szükség van egy csomó erőforrásokat, hogy a vonat egy <abbr title="Large Language Model">LLM</abbr>: ez közvetlenül lefordítja az időt és pénzt. Emiatt a vállalatok korlátozzák a képzés az új modell változatait. A modell relevanciája csökken az idő múlásával, mint az információ felhalmozódik és változik, míg az LLM adatbázis változatlan. Ezen túlmenően, LLM-k képzett nyilvános adatok-a természet, míg a legtöbb vállalat azt akarja, hogy lekérdezzék a magán adatokat is.


A Retrieval-Augmented Generation egy kétlépcsős folyamat.Az első lépésben az eszköz elemzi az adatokat, az LLM szerint vektorizálja őket, és egy vektor adatbázisban tárolja őket; a másodikban az eszköz az adatbázist további adatokként használja az LLM lekérdezésekor.

Kontextus jegyzőkönyv

Az LLM statikus jellegének legújabb kezelési módja az MCP.


Az MCP egy nyílt protokoll, amely szabványosítja, hogy az alkalmazások hogyan nyújtanak kontextust az LLM-eknek. Gondolj az MCP-re, mint egy USB-C portra az AI-alkalmazásokhoz. Ahogy az USB-C szabványosított módot biztosít az eszközöknek a különböző perifériákhoz és tartozékokhoz való csatlakoztatására, az MCP szabványosított módot biztosít az AI modelleknek a különböző adatforrásokhoz és eszközökhöz való csatlakoztatására.


-- Kezdje el a Model Context Protocol alkalmazást

Az MCP egy nyílt protokoll, amely szabványosítja, hogy az alkalmazások hogyan nyújtanak kontextust az LLM-eknek. Gondolj az MCP-re, mint egy USB-C portra az AI-alkalmazásokhoz. Ahogy az USB-C szabványosított módot biztosít az eszközöknek a különböző perifériákhoz és tartozékokhoz való csatlakoztatására, az MCP szabványosított módot biztosít az AI modelleknek a különböző adatforrásokhoz és eszközökhöz való csatlakoztatására.


- - -Indítsa el a Model Context Protocol alkalmazást


Az MCP-nek két előnye van a RAG-hoz képest:


  • 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!


Az MCP meghatározásaKét közlekedési alternatívaÜgyfél-szerver kommunikáció esetén:


  • stdio: Az ügyfél elindítja az alfolyamatot, és a kommunikáció a standardon és a standardon túl történik.
  • HTTP a Server-Sent eseményekkel

A megoldás építése

A fenti elmélet után most készen állunk a gyakorlati részre. Ez egy MCP szerver kiválasztásával kezdődik.Itt azEz egy jó kiindulópont, de ahivatalos GitHub MCP szerverMert a LangChain4J dokumentáció említi.


A GitHub MCP szerver aStúdióEz azt jelenti, hogy meg kell kapnunk a bináris és indítsa el az alkalmazás. Ez gyors, mint a HTTP szállítás, de figyelembe véve a teljes időt, amely magában foglalja a HTTP hívás a modell és a számítási idő az oldalán, ez irreleváns.


Néhány kutatás után kiderült, hogy aProxy szolgáltatásprojekt. Lehetővé teszi, hogy stdio-ról HTTP-re vagy HTTP-ről stdio-ra váltson. Docker-képként is elérhető.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
  1. Letöltés archívum
  2. Kivonja azt
  3. Távolítsa el az archívumot
  4. A bináris végrehajthatóvá válik


Megjegyzendő, hogy nem tudjuk meghatározni aCMDmivel a bináris csak a port és a host paraméterekkel történő konfigurálását teszi lehetővé. ebből az okból el kell halasztanunk a parancsot a futási időben, vagy az én esetemben adocker-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
  1. Szükségünk van egy GITHUB_PERSONAL_ACCESS_TOKEN környezeti változóra érvényes tokennel a GitHub hitelesítéséhez
  2. Az összes környezeti változó átadása az alfolyamatba
  3. A meghallgatási port beállítása
  4. Csatlakozás bármely IP-hez
  5. A proxy a dash után "kapcsolja" a stdio MCP szervert
  6. Indítsa el a szervert az összes beállítással


A kép biztosítja a/sseA 8080-as porton érhető el.

A megoldás kódolása

A kódolás a legegyszerűbb. lefelé aLangChain4J dokumentáció az MCP-rőlA projektben a következőképpen fordítják le:


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)
    }
}
  1. ConfigurationProperty osztályt adtam hozzá az SSE URL paraméterezéséhez
  2. Az MCP protokoll lehetővé teszi a naplók visszaküldését a klienshez.
  3. Nem szükséges, de segített annak biztosításában, hogy a kliens csatlakozik a szerverhez, és felsorolja a rendelkezésre álló eszközöket.
  4. Csatlakoztassa a fentiekben létrehozott MCP-eszköz-szolgáltatót a AiServices


Ebben a pillanatban a modellnek továbbítania kell a regisztrált eszközök bármelyikének megfelelő kérést az MCP-kiszolgálóra.


curl -N -H 'Content-Type: application/json' localhost:8080 -d '{ "sessionId": "1", "text": "What are my top three most popular GitHub repos?" }'


Többször megpróbáltam, és a válaszokat ezeken a vonalakon kaptam:


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.


A modell egyszerűen figyelmen kívül hagyta az eszközöket, annak ellenére, hogy a dokumentáció az ellenkezőjét állítja.

A megoldás rögzítése

Elolvastam a LangChain4J dokumentációt néhányszor, de haszontalanul. Megpróbáltam használni az OpenAI-t és egy maroknyi más AI-eszközt sikertelenül. A legtöbb válasz megerősítette, hogy ki kell dolgoznia a dobozból. Néhányan megemlítették, hogy közvetlenül hívják az eszközt, ami legyőzi a célt; egyik megemlítette, hogy Ollama nem támogatja az eszközöket. Ellenőriztem az Ollama blogot: bejelentette az eszközök támogatását 2024-ben.


Az elkülönített architektúra több mozgó darabot vezet be. gyanítottam, hogy valami rossz lehet az egész hívási láncban. eltávolítottam az MCP proxy-t, hozzáadtam agithub-mcp-serverközvetlenül az alkalmazás képre, és a kódot HTTP-ről stdio-ra változtatta.


Majdnem feladtam, amikor úgy döntöttem, hogy visszatérek a gyökerekhez.Példa a dokumentációbólEz volt az én ha-ha pillanatom.


A minta OpenAI-t használ, miközben Ollama-t használtam. megpróbáltam MCP-t OpenAI-val, Mistral AI-val és Ollamával. Csak az OpenAI modell működik az MCP-vel. ugyanazt a kérést küldtem el, mint fent:


curl -N -H 'Content-Type: application/json' localhost:8080 -d '{ "sessionId": "1", "text": "What are my top three most popular GitHub repos?" }'


Most az OpenAI helyesen ábrázolja a kérést a megfelelő eszközre, és visszaadja a várt választ:


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.%    


Mivel egy hitelesítési tokent továbbítunk az MCP szerverre, amely átadja azt a GitHub API-nak, az utóbbi tudja, hogy melyik felhasználó teszi a hívást.my reposBevallom, hogy ez egy szokatlan használati eset a rendszeres webes alkalmazások számára, amelyek több felhasználót szolgálnak ki, de mindegyikben egyetlen hitelesítési tokent használnak.


Egyéb gyakori kérdések,Az e.gA legnépszerűbb tárhelyek a GitHub-on relevánsak a webes alkalmazásokhoz, mivel nincsenek implicit kontextusuk – a felhasználó.

következtetés

Ennek a bejegyzésnek a középpontjában az MCP-kiszolgáló integrációja áll egy LangChain4J alkalmazásban.A konfiguráció a dokumentációnak köszönhetően egyszerű, de van néhány figyelmeztetés.


Először is, az, hogy az MCP szerver hogyan illeszkedik az architektúrájába, még mindig rajtad múlik.mcp-proxyEzután a LangChain4J úgy tűnik, hogy egy szivárgó absztrakció. Mindent megtesz, hogy erős absztrakciós réteget biztosítson Önnek, de az alatta lévő megvalósítások nem egyenlőek.


Megtanultam az MCP-ről a valós világban, és ez elég sok ajtót nyitott a projekt ötletekre.


A cikk teljes forráskódja megtalálható aGitHub szolgáltatás.


To go further:


  • Indítsa el a Model Context Protocol alkalmazást
  • Keressen remek MCP szervereket és klienseket
  • LangChain4J - Modellező kontextus protokoll (MCP)



Eredetileg közzétett A Java Geek április 27, 2025

Egy Java Geek

Trending Topics

blockchaincryptocurrencyhackernoon-top-storyprogrammingsoftware-developmenttechnologystartuphackernoon-booksBitcoinbooks
OSZAR »