187 lượt đọc

Đánh giá LangChain4J 6 tháng sau

từ tác giả Nicolas Fränkel11m2025/05/01
Read on Terminal Reader

dài quá đọc không nổi

Trọng tâm chính của bài đăng này là tích hợp một máy chủ MCP trong một ứng dụng LangChain4J. Trong khi cấu hình là đơn giản nhờ tài liệu, có một số cảnh báo.
featured image - Đánh giá LangChain4J 6 tháng sau
Nicolas Fränkel HackerNoon profile picture

Năm ngoái,Tôi bắt đầu đập một chútxung quanhTải LangChain4JĐó là một dự án phát triển nhanh chóng, và tôi muốn làm quen với các bản cập nhật. tôi cũng muốn kiểm tra làm thế nào để tích hợp một máy chủ Model Context Protocol trong LangChain4J.

Phiên bản beta 1

Tôi đã viết bài đăng cuối cùng của mình vào tháng 11 năm 2024 và sử dụng phiên bản mới nhất có sẵn vào thời điểm đó, v0.35. LangChain4J bắt đầu hành trình hướng tới 1.0 vào tháng 12 năm ngoái.

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 tháng 9 năm 2024

035.0 người

Ngày 22 tháng 12 năm 2024

1.0.0-Alpha1 của chúng tôi

10 tháng 2 năm 2025

1.0.1 Cấu hình beta1

Ngày 13 tháng 3 năm 2025

1.0.1 Bêta2

12 Tháng Tư, 2025

Đánh giá 1.0-Beta3


LangChain4J Tiếp theoSemverNgười bảo trì đã sử dụng cơ hội này để giới thiệu những thay đổi phá vỡ.Trong trường hợp của tôi, tôi đã phải cập nhật mã của mình để tính đến những thay đổi API phá vỡ.

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()
)

Đa số = nhiều ( )
Độc Lập()
.onBackpressureBuffer<String>()
chatBot.talk (m.sessionId, m.text)
.onNext(s::tryEmitTiếp theo)
.onError(s::tryEmitThất bại)
Đầy Đủ
Thảo luận(
Bắt đầu ( )
Trả lời Trả lời Trả lời Trả lời Trả lời
c.asFlux().asFlow()
)

Đa số = nhiều ( )
Độc Lập()
.onBackpressureBuffer<String>()
chatBot.talk (m.sessionId, m.text)
.onChính trịTrả lời(s::tryEmitNext)
.onError(s::tryEmitThất bại)
Trả lời trọn vẹn
Thảo luận(
Bắt đầu ( )
Trả lời Trả lời Trả lời Trả lời Trả lời
c.asFlux().asFlow()
)

Dự án Reactor Integration

LangChain4J cung cấp tích hợp dự án Reactor; tôi đã bỏ lỡ nó trong những lần đọc trước.a lot.

Tôi đang sử dụngAiServices, vì vậy trước đây tôi đã xác định một giao diện cho LangChain4J để triển khai trong thời gian chạy:


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


Chúng ta nên thêm sự phụ thuộc sau:


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


Bây giờ chúng ta có thể thay đổi kiểu trả về từ aFlux<String>2 aTokenStreamĐây là chữ ký cập nhật:


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


Nó làm cho việc tạo ra cácsinktrên không cần thiết. chúng ta có thể đơn giản hóa mã như sau:


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


Hãy nhớ rằng hai ngày gỡ lỗi có thể dễ dàng tiết kiệm cho bạn hai giờ đọc tài liệu!

Tích hợp một Model Context Protocol Server

Trong phần này, tôi muốn tích hợp một <abbr title="Model Context Protocol">MCP</abbr> trong ứng dụng LangChain4J của tôi.

Retrieval-Augmented thế hệ

Một người cần rất nhiều nguồn lực để đào tạo một <abbr title="Large Language Model">LLM</abbr>: nó trực tiếp chuyển thành thời gian và tiền bạc. Vì lý do này, các công ty hạn chế việc đào tạo các phiên bản mô hình mới. Sự liên quan của một mô hình giảm theo thời gian khi thông tin tích lũy và thay đổi, trong khi cơ sở dữ liệu của LLM là không thay đổi.


Retrieval Augmented Generation là cách truyền thống để đối phó với những giới hạn này. Retrieval-Augmented Generation là một quá trình hai bước. Trong bước đầu tiên, công cụ phân tích dữ liệu, vectorizes nó theo LLM, và lưu trữ nó trong một cơ sở dữ liệu vector; trong thứ hai, công cụ sử dụng cơ sở dữ liệu như dữ liệu bổ sung khi truy vấn LLM.

Mô hình context protocol

Cách mới nhất để xử lý bản chất tĩnh của LLM là MCP.


MCP là một giao thức mở tiêu chuẩn hóa cách các ứng dụng cung cấp bối cảnh cho LLM. Hãy nghĩ về MCP như một cổng USB-C cho các ứng dụng AI. Cũng giống như USB-C cung cấp một cách tiêu chuẩn hóa để kết nối các thiết bị của bạn với các thiết bị ngoại vi và phụ kiện khác nhau, MCP cung cấp một cách tiêu chuẩn hóa để kết nối các mô hình AI với các nguồn dữ liệu và công cụ khác nhau.


Bắt đầu với Model Context Protocol

MCP là một giao thức mở tiêu chuẩn hóa cách các ứng dụng cung cấp bối cảnh cho LLM. Hãy nghĩ về MCP như một cổng USB-C cho các ứng dụng AI. Cũng giống như USB-C cung cấp một cách tiêu chuẩn hóa để kết nối các thiết bị của bạn với các thiết bị ngoại vi và phụ kiện khác nhau, MCP cung cấp một cách tiêu chuẩn hóa để kết nối các mô hình AI với các nguồn dữ liệu và công cụ khác nhau.


Bắt đầu với Model Context Protocol


MCP có hai lợi thế so với 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 định nghĩa2 Thay thế giao thôngĐối với giao tiếp client-server:


  • stdio: Khách hàng khởi động một quá trình phụ, và giao tiếp xảy ra trên tiêu chuẩn trong và tiêu chuẩn ra
  • HTTP với Server-Sent Events

Kiến trúc giải pháp

Sau lý thuyết trên, bây giờ chúng ta đã sẵn sàng cho phần thực hành. nó bắt đầu bằng cách chọn một máy chủ MCP.Ở đâylà một điểm khởi đầu tốt. tuy nhiên, tôi đã chọnMáy chủ GitHub MCPbởi vì tài liệu LangChain4J đề cập đến nó.


GitHub MCP Server cung cấpStudioNó có nghĩa là chúng ta nên lấy nhị phân và bắt đầu nó từ ứng dụng. Nó nhanh hơn so với vận chuyển HTTP, nhưng với tổng thời gian bao gồm cuộc gọi HTTP đến mô hình và thời gian tính toán ở phía bên, nó không liên quan. Từ quan điểm kiến trúc, tôi sẽ thích một thành phần chuyên dụng với quá trình của nó.


Sau một số nghiên cứu, tôi tìm thấy nhữngMcp ProxyDự án. Nó cho phép bạn chuyển từ stdio sang HTTP hoặc từ HTTP sang stdio. Nó cũng có sẵn dưới dạng hình ảnh Docker. Chúng tôi có thể kết hợp cả máy chủ và proxy với cácDockerfile:


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. Download tập tin
  2. Extract nó
  3. Loại bỏ Archive
  4. Tạo Binary Executable


Lưu ý rằng chúng ta không thể xác địnhCMDvì nhị phân chỉ cho phép cấu hình cổng và máy chủ với các thông số. vì lý do này, chúng ta phải trì hoãn lệnh tại thời gian chạy, hoặc trong trường hợp của tôi, trongdocker-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. Chúng tôi cần một biến môi trường GITHUB_PERSONAL_ACCESS_TOKEN với một token hợp lệ để xác thực trên GitHub
  2. Chuyển tất cả các biến môi trường sang quá trình phụ
  3. Cài đặt cổng nghe
  4. Kết nối với bất kỳ IP nào
  5. Proxy "liên kết" với máy chủ stdio MCP sau khi dash
  6. Chạy máy chủ với tất cả các tùy chọn được bật


Hình ảnh sẽ cung cấp/sseCổng kết nối 8080

Mã hóa giải pháp

Phần mã hóa là dễ nhất. Head down to theTài liệu LangChain4J về MCPvà tiếp tục. Trong dự án, nó dịch như sau:


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. Tôi đã thêm một lớp ConfigurationProperty để tham số hóa URL SSE
  2. Giao thức MCP cung cấp một cách để gửi nhật ký trở lại cho khách hàng
  3. Không cần thiết, nhưng nó giúp tôi đảm bảo rằng máy khách kết nối với máy chủ và có thể liệt kê các công cụ được cung cấp
  4. Plug vào nhà cung cấp công cụ MCP được tạo ở trên trong AiServices


Tại thời điểm này, mô hình nên chuyển một yêu cầu phù hợp với bất kỳ công cụ đã đăng ký nào đến máy chủ MCP.


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


Tôi đã thử nhiều lần, và tôi nhận được câu trả lời theo các dòng này:


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.


Mô hình chỉ đơn giản là bỏ qua các công cụ mặc dù tài liệu tuyên bố ngược lại.

Sửa chữa giải pháp

Tôi đã đọc tài liệu LangChain4J một vài lần, nhưng vô ích. Tôi đã cố gắng sử dụng OpenAI và một số công cụ AI khác mà không thành công. Hầu hết các câu trả lời xác nhận nó nên làm việc ra khỏi hộp. Một số đề cập đến việc gọi công cụ trực tiếp, điều này đánh bại mục đích; một đề cập đến Ollama không hỗ trợ công cụ. Tôi kiểm tra blog Ollama: nó công bố hỗ trợ công cụ vào năm 2024.


Kiến trúc tách nối giới thiệu nhiều mảnh chuyển động hơn.Tôi nghi ngờ có điều gì đó có thể không ổn trong toàn bộ chuỗi cuộc gọi.Tôi đã loại bỏ proxy MCP, thêmgithub-mcp-servertrực tiếp vào hình ảnh ứng dụng, và thay đổi mã từ HTTP sang stdio.


Tôi sắp từ bỏ khi tôi quyết định quay trở lại gốc rễ.Mẫu từ tài liệu: nó chỉ làm việc! đó là khoảnh khắc ha-ha của tôi.


Mẫu sử dụng OpenAI, trong khi tôi đang sử dụng Ollama.Tôi đã thử MCP với OpenAI, Mistral AI, và Ollama.Chỉ có mô hình OpenAI hoạt động với MCP.Tôi đã gửi cùng một yêu cầu như trên:


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


Bây giờ, OpenAI chính xác lập bản đồ yêu cầu đến công cụ chính xác và trả về câu trả lời mà tôi mong đợi:


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


Bởi vì chúng tôi truyền một mã thông báo xác thực cho máy chủ MCP, mà truyền nó đến API GitHub, sau này biết người dùng nào thực hiện cuộc gọi.my reposTôi thừa nhận rằng đó là một trường hợp sử dụng bất thường cho các ứng dụng web thông thường phục vụ nhiều người dùng, nhưng sử dụng một token xác thực duy nhất mỗi.


Những câu hỏi thường gặp khác,e.g, tìm các kho lưu trữ phổ biến nhất trên GitHub, có liên quan đến các ứng dụng web, vì chúng không có bối cảnh ngụ ý – người dùng.

Kết luận

Trọng tâm chính của bài đăng này là tích hợp một máy chủ MCP trong một ứng dụng LangChain4J. Trong khi cấu hình là đơn giản nhờ tài liệu, có một số cảnh báo.


Đầu tiên, làm thế nào máy chủ MCP phù hợp với kiến trúc của bạn vẫn còn tùy thuộc vào bạn. tôi đã phải sáng tạo để làm cho nó tách ra, sử dụng tuyệt vờimcp-proxySau đó, LangChain4J dường như là một sự trừu tượng rò rỉ. Nó làm mọi thứ có thể để cung cấp cho bạn một lớp trừu tượng mạnh mẽ, nhưng các ứng dụng bên dưới nó bảo vệ bạn khỏi không bằng nhau.


Tôi đã học được về MCP trong thế giới thực, và nó đã mở ra khá nhiều cánh cửa cho các ý tưởng dự án.


Mã nguồn đầy đủ cho bài viết này có thể được tìm thấy tạiGitHub.


To go further:


  • Bắt đầu với Model Context Protocol
  • Tìm máy chủ và khách hàng MCP tuyệt vời
  • LangChain4J - Giao thức ngữ cảnh mô hình (MCP)



Ban đầu được xuất bản trên A Java Geek vào ngày 27 tháng 4 năm 2025.

Tên Java Geek

Trending Topics

blockchaincryptocurrencyhackernoon-top-storyprogrammingsoftware-developmenttechnologystartuphackernoon-booksBitcoinbooks