187 skaitymai

LangChain4J peržiūra po 6 mėnesių

pateikė Nicolas Fränkel11m2025/05/01
Read on Terminal Reader

Per ilgai; Skaityti

Pagrindinis šio įrašo dėmesys skiriamas MCP serverio integravimui į LangChain4J programą. Nors konfigūracija yra paprasta dėka dokumentacijos, yra keletas įspėjimų.
featured image - LangChain4J peržiūra po 6 mėnesių
Nicolas Fränkel HackerNoon profile picture

Praėjusiais metais,Aš pradėjau šiek tiekAplinkŠilutė4JTai sparčiai augantis projektas, ir aš norėjau susipažinti su atnaujinimais. taip pat norėjau patikrinti, kaip integruoti Model Context Protocol serverį LangChain4J.

1 beta versija

Aš parašiau savo paskutinį pranešimą 2024 m. Lapkričio mėn. Ir naudojau naujausią tuo metu turimą versiją, v0.35. LangChain4J pradėjo savo kelionę į 1.0 gruodį.

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

Rugsėjo 25, 2024

0 35 0

gruodžio 22, 2024

1 alfa1 alfa1

Vasario 10, 2025

Įrašai 1.0-beta1

Kovo 13, 2025

Įrašai 1.0-Beta2

balandžio 12, 2025

Įrašai 1.0-Beta3


LangChain4J pristatymasSemverėTvarkytojai pasinaudojo proga įvesti pažeidžiančius pakeitimus. Mano atveju turėjau atnaujinti savo kodą, kad būtų atsižvelgta į pažeidžiančius API pakeitimus.

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 = Sinks.many()
Išskirtinis (
.onBackpressureBuffer<String>()
chatBot.talk (m.sessionId, m.text)
.onKitas(s::TryEmitKitas)
.onError(s::tryEmitError) klaidos
Neužbaigtas
SėkmėSėkmėSėkmė(
Pradžia » Pradžia
Atsižvelgdamas į tai, kad esate įsitikinęs, kad esate įsitikinęs, kad esate įsitikinęs, kad esate (
s.asFlux().asFlow()
)

Val s = Sinks.many()
Išskirtinis (
.onBackpressureBuffer<String>()
chatBot.talk (m.sessionId, m.text)
Atsakymas į šį klausimą(s::tryEmitNext)
.onError(s::tryEmitError) klaidos
Užpildyti atsakymą {
SėkmėSėkmėSėkmė(
Pradžia » Pradžia
Atsižvelgdamas į tai, kad esate įsitikinęs, kad esate įsitikinęs, kad esate įsitikinęs, kad esate (
s.asFlux().asFlow()
)

Reaktoriaus integracijos projektas

LangChain4J siūlo „Project Reactor“ integraciją; aš praleidau ją ankstesniuose minėjimuose.a lot.

Aš naudojuAiServices, todėl aš anksčiau apibrėžiau LangChain4J sąsają, kurią reikia įgyvendinti paleidimo metu:


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


Reikėtų pridėti tokią priklausomybę:


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


Dabar galime pakeisti grąžinimo tipą iš aFlux<String>Dvi ATokenStreamŠtai atnaujintas parašas:


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


Tai leidžia sukurtisinkMes galime supaprastinti kodą taip:


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


Atminkite, kad dvi dienų debugging gali lengvai sutaupyti jums dvi valandas skaityti dokumentaciją!

Kontekstinio protokolo serverio integravimas

Šiame skyriuje noriu integruoti <abbr title="Model Context Protocol">MCP</abbr> į savo LangChain4J programą.

Išplėstinės kartos

Reikia daug ir daug išteklių mokyti <abbr title="Large Language Model">LLM</abbr>: jis tiesiogiai verčiasi į laiką ir pinigus. Dėl šios priežasties įmonės riboja naujų modelio versijų mokymą. Modelio aktualumas laikui bėgant mažėja, nes informacija kaupiasi ir keičiasi, o LLM duomenų bazė yra nekintama.


Retrieval Augmented Generation buvo tradicinis būdas susidoroti su šiomis ribomis. Retrieval-Augmented Generation yra dviejų žingsnių procesas. Pirmuoju žingsniu įrankis analizuoja duomenis, vektorizuoja juos pagal LLM ir saugo juos vektoriaus duomenų bazėje; antra, įrankis naudoja duomenų bazę kaip papildomus duomenis, kai užklausos LLM.

Kontekstinis protokolo modelis

Naujausias būdas tvarkyti statinį LLM pobūdį yra MCP.


MCP yra atviras protokolas, kuris standartizuoja, kaip programos teikia kontekstą LLM. Pagalvokite apie MCP kaip USB-C prievadą AI programoms. Taip pat, kaip USB-C suteikia standartizuotą būdą prijungti savo įrenginius prie įvairių periferinių įrenginių ir priedų, MCP suteikia standartizuotą būdą prijungti AI modelius prie skirtingų duomenų šaltinių ir įrankių.


- Pradėkite nuo modelio konteksto protokolo

MCP yra atviras protokolas, kuris standartizuoja, kaip programos teikia kontekstą LLM. Pagalvokite apie MCP kaip USB-C prievadą AI programoms. Taip pat, kaip USB-C suteikia standartizuotą būdą prijungti savo įrenginius prie įvairių periferinių įrenginių ir priedų, MCP suteikia standartizuotą būdą prijungti AI modelius prie skirtingų duomenų šaltinių ir įrankių.


- Pradėkite nuo modelio konteksto protokolo


MCP turi du privalumus prieš 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 apibrėžiaDvi transporto alternatyvosKlientų ir serverių ryšys:


  • stdio: klientas paleidžia subprocesą, o bendravimas vyksta per standartą ir standartą
  • HTTP su serverio siunčiamais įvykiais

Sprendimo architektūra

Po aukščiau pateiktos teorijos mes dabar esame pasirengę praktinei daliai.čiaTai puiki pradžia, tačiau aš nusprendžiauGitHub MCP serverisTodėl, kad LangChain4J dokumentacija tai nurodo.


GitHub MCP serveris siūloStadijaTai reiškia, kad turėtume gauti dvejetainį ir pradėti jį iš programos. Jis yra greitas, palyginti su HTTP transportu, bet atsižvelgiant į bendrą laiką, kurį sudaro HTTP skambutis į modelį ir skaičiavimo laikas jo pusėje, tai nėra svarbu.


Atlikus tam tikrus tyrimus, radau„Mcp Proxy“Projektas.Jis leidžia jums perjungti arba iš stdio į HTTP arba iš HTTP į stdio.Jis taip pat prieinamas kaip Docker vaizdas.Mes galime sujungti tiek serverį, tiek proxy su: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. Atsisiųskite archyvą
  2. Išimkite jį
  3. Ištrinti archyvą
  4. Padarykite binarinį vykdytiną


Atkreipkite dėmesį, kad mes negalime apibrėžtiCMDkaip dvejetainis leidžia tik konfigūruoti prievadą ir šeimininką su parametrais. Dėl šios priežasties mes turime atidėti komandą paleidimo metu, arba mano atveju,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
  1. Mums reikia GITHUB_PERSONAL_ACCESS_TOKEN aplinkos kintamojo su galiojančiu ženklu, kad galėtume autentifikuoti „GitHub“
  2. Perkelti visus aplinkos kintamuosius į subprocesą
  3. Įveskite klausymo prievadą
  4. Prisijungti prie bet kokio IP
  5. Proxy "jungiasi" su stdio MCP serveriu po valdymo
  6. paleiskite serverį su visomis įgalintomis parinktimis


Vaizdas suteiks/sseĮjungtas 8080 portas.

Kodavo sprendimą

Kodavimo dalis yra lengviausia.LangChain4J dokumentacija apie MCPir sekite toliau.Projekte jis išverčiamas taip:


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. Pridėjau „ConfigurationProperty“ klasę, kad parametrizuotumėte SSE URL
  2. MCP protokolas suteikia būdą siųsti žurnalus atgal į klientą
  3. Nereikia, bet tai padėjo man įsitikinti, kad klientas prisijungė prie serverio ir galėjo išvardyti pateiktus įrankius
  4. Prijunkite MCP įrankių teikėją, sukurtą aukščiau AiServices


Šiuo metu modelis turėtų perduoti užklausą, atitinkančią bet kurį iš registruotų įrankių, į MCP serverį.


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


Aš bandžiau keletą kartų, ir aš gavau atsakymus šiomis kryptimis:


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.


Modelis tiesiog ignoruoja įrankius, nepaisant to, kad dokumentai teigia priešingai.

Išspręsti sprendimą

Aš perskaičiau LangChain4J dokumentaciją keletą kartų, bet be jokios naudos. Aš bandžiau naudoti OpenAI ir keletą kitų AI įrankių be sėkmės. Dauguma atsakymų patvirtino, kad tai turėtų dirbti iš dėžutės. Kai kurie minėjo tiesiogiai skambinant įrankiui, kuris nugalėjo tikslą; vienas minėjo, kad Ollama nepalaiko įrankių. Patikrinau Ollama tinklaraštį: jis paskelbė įrankių palaikymą 2024.


Atjungta architektūra įveda daugiau judančių dalių. Įtariau, kad kažkas gali būti negerai visoje skambučių grandinėje.github-mcp-servertiesiogiai į programos vaizdą ir pakeitė kodą iš HTTP į stdio.


Aš buvau pasiruošęs atsisakyti, kai nusprendžiau grįžti prie šaknų.Pavyzdys iš dokumentacijosTai buvo mano ha-ha momentas.


Pavyzdys naudoja OpenAI, o aš naudoju Ollama. Aš išbandžiau MCP su OpenAI, Mistral AI ir Ollama. Tik OpenAI modelis veikia su MCP. Aš atsiuntė tą patį prašymą, kaip ir aukščiau:


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


Dabar OpenAI teisingai nukreipia užklausą į teisingą įrankį ir grąžina atsakymą, kurio tikėjausi:


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


Kadangi mes perduodame autentifikavimo žetoną MCP serveriui, kuris jį perduoda GitHub API, pastarasis žino, kuris vartotojas atlieka skambutį.my reposAš pripažįstu, kad tai yra neįprastas naudojimo atvejis įprastoms žiniatinklio programoms, kurios aptarnauja kelis vartotojus, bet naudoja vieną autentifikavimo žetoną.


Kiti įprasti klausimai,e. g, rasti populiariausius saugyklas GitHub, yra susiję su žiniatinklio programomis, nes jie neturi netiesioginio konteksto - vartotojas.

Išvada

Pagrindinis šio įrašo dėmesys skiriamas MCP serverio integravimui į LangChain4J programą. Nors konfigūracija yra paprasta dėka dokumentacijos, yra keletas įspėjimų.


Pirma, kaip MCP serveris tinka jūsų architektūrai, vis dar priklauso nuo jūsų.mcp-proxyTada LangChain4J atrodo kaip nutekėjusi abstrakcija.Ji daro viską, kas įmanoma, kad suteiktų jums stiprią abstrakcijos sluoksnį, tačiau įgyvendinimai po juo apsaugo jus nuo nėra lygūs.


Sužinojau apie MCP realiame pasaulyje, ir tai atvėrė keletą durų projektų idėjoms.


Visą šio įrašo kodą galima rasti„GitHub“.


To go further:


  • Pradėkite nuo modelio konteksto protokolo
  • Rasti puikius MCP serverius ir klientus
  • LangChain4J - Modelio konteksto protokolas (MCP)



Iš pradžių paskelbta A Java Geek balandžio 27, 2025

Java Geek žaidimai
L O A D I N G
. . . comments & more!

About Author

Nicolas Fränkel HackerNoon profile picture
Nicolas Fränkel@nfrankel
Dev Advocate | Developer & architect | Love learning and passing on what I learned!

PABAIGTI ŽYMES

ŠIS STRAIPSNIS BUVO PRISTATYMAS...

Trending Topics

blockchaincryptocurrencyhackernoon-top-storyprogrammingsoftware-developmenttechnologystartuphackernoon-booksBitcoinbooks