J-LangChain - 复杂智能链流式执行

系列文章索引
J-LangChain 入门

介绍

j-langchain是一个Java版的LangChain开发框架,具有灵活编排和流式执行能力,旨在简化和加速各类大模型应用在Java平台的落地开发。它提供了一组实用的工具和类,使得开发人员能够更轻松地构建类似于LangChain的Java应用程序。

github: https://github.com/flower-trees/j-langchain

复杂智能链流式执行实例

1、分支路由

根据 chain 输入参数 vendor,判断使用 llama3gpt-4、还是回复 无法回答

在这里插入图片描述

LangChain实现

from langchain_openai import ChatOpenAI
from langchain_core.runnables import RunnableLambda, RunnablePassthrough
from langchain_ollama import OllamaLLM
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParserprompt = ChatPromptTemplate.from_template("tell me a joke about ${topic}")
def route(info):if "ollama" in info["vendor"]:return prompt | OllamaLLM(model="llama3:8b")elif "chatgpt" in info["vendor"]:return prompt | ChatOpenAI(model="gpt-4")else:return prompt | RunnableLambda(lambda x: "sorry, I don't know how to do that")chain = route | StrOutputParser()result = chain.stream({"topic": "bears", "vendor": "ollama"})
for chunk in result:print(chunk, end="", flush=False)

J-LangChain实现

使用 flow组件 原生功能 .next() 实现分支执行 子chain

FlowInstance chain = chainActor.builder().......next(Info.c("vendor == 'ollama'", chatOllama),Info.c("vendor == 'chatgpt'", chatOpenAI),Info.c(input -> "sorry, I don't know how to do that"))......
public void SwitchDemo() {BaseRunnable<StringPromptValue, ?> prompt = PromptTemplate.fromTemplate("tell me a joke about ${topic}");ChatOllama chatOllama = ChatOllama.builder().model("llama3:8b").build();ChatOpenAI chatOpenAI = ChatOpenAI.builder().model("gpt-4").build();FlowInstance chain = chainActor.builder().next(prompt).next(Info.c("vendor == 'ollama'", chatOllama),Info.c("vendor == 'chatgpt'", chatOpenAI),Info.c(input -> "sorry, I don't know how to do that")).next(new StrOutputParser()).build();ChatGenerationChunk chunk = chainActor.stream(chain, Map.of("topic", "bears", "vendor", "ollama"));StringBuilder sb = new StringBuilder();while (chunk.getIterator().hasNext()) {sb.append(chunk.getIterator().next());System.out.println(sb);}
}

2、组合嵌套

主chain 调用 子chain 生成一个笑话,并对笑话是否可笑进行评价。

在这里插入图片描述

LangChain实现

from langchain_ollama import OllamaLLM
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParsermodel = OllamaLLM(model="llama3:8b")
prompt = ChatPromptTemplate.from_template("tell me a joke about {topic}")chain = prompt | model | StrOutputParser()analysis_prompt = ChatPromptTemplate.from_template("is this a funny joke? {joke}")
composed_chain = {"joke": chain} | analysis_prompt | model | StrOutputParser()result = composed_chain.stream({"topic": "bears"})
for chunk in result:print(chunk, end="", flush=False)

J-LangChain实现

flow组件 原生功能支持嵌套执行。

💡 Notes:

  • 这里需要 .next(new InvokeChain(chain)) 来一次性调用嵌套链,返回结果。
public void ComposeDemo() throws TimeoutException {ChatOllama llm = ChatOllama.builder().model("llama3:8b").build();StrOutputParser parser = new StrOutputParser();BaseRunnable<StringPromptValue, ?> prompt = PromptTemplate.fromTemplate("tell me a joke about ${topic}");FlowInstance chain = chainActor.builder().next(prompt).next(llm).next(parser).build();BaseRunnable<StringPromptValue, ?> analysisPrompt = PromptTemplate.fromTemplate("is this a funny joke? ${joke}");FlowInstance analysisChain = chainActor.builder().next(new InvokeChain(chain)) //invoke 执行嵌套链.next(input -> { System.out.printf("joke content: '%s' \n\n", input); return input; }).next(input -> Map.of("joke", ((Generation)input).getText())).next(analysisPrompt).next(llm).next(parser).build();ChatGenerationChunk chunk = chainActor.stream(analysisChain, Map.of("topic", "bears"));StringBuilder sb = new StringBuilder();while (chunk.getIterator().hasNext()) {sb.append(chunk.getIterator().next());System.out.println(sb);}
}

3、并行执行

主chain 并行执行 joke_chainpoem_chain,并交替输出stream答案。

在这里插入图片描述

LangChain实现

from langchain_core.runnables import RunnableParalleljoke_chain = ChatPromptTemplate.from_template("tell me a joke about {topic}") | model
poem_chain = ChatPromptTemplate.from_template("write a 2-line poem about {topic}") | modelparallel_chain = RunnableParallel(joke=joke_chain, poem=poem_chain)result = parallel_chain.stream({"topic": "bear"})joke = "joke: "
poem = "poem: "
for chunk in result:if 'joke' in chunk:  joke += chunk['joke']print(joke, flush=True)if 'poem' in chunk:poem += chunk['poem']print(poem, flush=True)

输出:

joke: Why
joke: Why did
joke: Why did the
poem: Bear
joke: Why did the bear
poem: Bear stands
joke: Why did the bear break
poem: Bear stands tall
joke: Why did the bear break up
poem: Bear stands tall,
joke: Why did the bear break up with
poem: Bear stands tall, wise
joke: Why did the bear break up with his
poem: Bear stands tall, wise and
......

J-LangChain实现

使用 flow组件 原生功能 .concurrent() 实现并发执行。

FlowInstance chain = chainActor.builder().concurrent((IResult<Map<String, AIMessageChunk>>) (iContextBus, isTimeout) ->Map.of("joke", iContextBus.getResult(jokeChain.getFlowId()), "poem", iContextBus.getResult(poemChain.getFlowId())),jokeChain, poemChain).build();

💡 Notes:

  • 这里 ChatOllama 并不是线程安全的,并发时需要 new 新实例。
public void ParallelDemo() {BaseRunnable<StringPromptValue, ?> joke = PromptTemplate.fromTemplate("tell me a joke about ${topic}");BaseRunnable<StringPromptValue, ?> poem = PromptTemplate.fromTemplate("write a 2-line poem about ${topic}");FlowInstance jokeChain = chainActor.builder().next(joke).next(ChatOllama.builder().model("llama3:8b").build()).build();FlowInstance poemChain = chainActor.builder().next(poem).next(ChatOllama.builder().model("llama3:8b").build()).build();FlowInstance chain = chainActor.builder().concurrent((IResult<Map<String, AIMessageChunk>>) (iContextBus, isTimeout) ->Map.of("joke", iContextBus.getResult(jokeChain.getFlowId()), "poem", iContextBus.getResult(poemChain.getFlowId())),jokeChain, poemChain).build();Map<String, AIMessageChunk> result = chainActor.stream(chain, Map.of("topic", "bears"));CompletableFuture.runAsync(() -> {AIMessageChunk jokeChunk = result.get("joke");StringBuilder jokeSb = new StringBuilder().append("joke: ");while (true) {try {if (!jokeChunk.getIterator().hasNext()) break;} catch (TimeoutException e) {throw new RuntimeException(e);}jokeSb.append(jokeChunk.getIterator().next().getContent());System.out.println(jokeSb);}});CompletableFuture.runAsync(() -> {AIMessageChunk poemChunk = result.get("poem");StringBuilder poemSb = new StringBuilder().append("poem: ");while (true) {try {if (!poemChunk.getIterator().hasNext()) break;} catch (TimeoutException e) {throw new RuntimeException(e);}poemSb.append(poemChunk.getIterator().next().getContent());System.out.println(poemSb);}}).join();
}

4、动态路由

chain 1 总结用户问题 topic主chain 根据 topic 动态路由执行 langchain_chainanthropic_chain、或者 general_chain

在这里插入图片描述

LangChain实现
通过 RunnableLambda 实现动态路由:

from langchain_core.prompts import PromptTemplate
from langchain_core.runnables import RunnableLambdachain = (PromptTemplate.from_template("""Given the user question below, classify it as either being about `LangChain`, `Anthropic`, or `Other`.Do not respond with more than one word.<question>
{question}
</question>Classification:""")| OllamaLLM(model="llama3:8b")| StrOutputParser()
)langchain_chain = PromptTemplate.from_template("""You are an expert in langchain. \
Always answer questions starting with "As Harrison Chase told me". \
Respond to the following question:Question: {question}
Answer:"""
) | OllamaLLM(model="llama3:8b")
anthropic_chain = PromptTemplate.from_template("""You are an expert in anthropic. \
Always answer questions starting with "As Dario Amodei told me". \
Respond to the following question:Question: {question}
Answer:"""
) | OllamaLLM(model="llama3:8b")
general_chain = PromptTemplate.from_template("""Respond to the following question:Question: {question}
Answer:"""
) | OllamaLLM(model="llama3:8b")def route(info):if "anthropic" in info["topic"].lower():return anthropic_chainelif "langchain" in info["topic"].lower():return langchain_chainelse:return general_chainfull_chain = {"topic": chain, "question": lambda x: x["question"]} | RunnableLambda(route)result = full_chain.stream({"question": "how do I use LangChain?"})
for chunk in result:print(chunk, end="", flush=False)

J-LangChain实现
使用 flow组件 原生的功能 .next() 实现动态路由:

FlowInstance fullChain = chainActor.builder().......next(Info.c("topic == 'anthropic'", anthropicChain),Info.c("topic == 'langchain'", langchainChain),Info.c(generalChain))......
public void RouteDemo() throws TimeoutException {ChatOllama llm = ChatOllama.builder().model("llama3:8b").build();BaseRunnable<StringPromptValue, Object> prompt = PromptTemplate.fromTemplate("""Given the user question below, classify it as either being about `LangChain`, `Anthropic`, or `Other`.Do not respond with more than one word.<question>${question}</question>Classification:""");FlowInstance chain = chainActor.builder().next(prompt).next(llm).next(new StrOutputParser()).build();FlowInstance langchainChain = chainActor.builder().next(PromptTemplate.fromTemplate("""You are an expert in langchain. \Always answer questions starting with "As Harrison Chase told me". \Respond to the following question:Question: ${question}Answer:""")).next(ChatOllama.builder().model("llama3:8b").build()).build();FlowInstance anthropicChain = chainActor.builder().next(PromptTemplate.fromTemplate("""You are an expert in anthropic. \Always answer questions starting with "As Dario Amodei told me". \Respond to the following question:Question: ${question}Answer:""")).next(ChatOllama.builder().model("llama3:8b").build()).build();FlowInstance generalChain = chainActor.builder().next(PromptTemplate.fromTemplate("""Respond to the following question:Question: ${question}Answer:""")).next(ChatOllama.builder().model("llama3:8b").build()).build();FlowInstance fullChain = chainActor.builder().next(new InvokeChain(chain)) //invoke 执行嵌套链.next(input -> { System.out.printf("topic: '%s' \n\n", input); return input; }).next(input -> Map.of("prompt", input, "question", ((Map<?, ?>)ContextBus.get().getFlowParam()).get("question"))).next(input -> { System.out.printf("topic: '%s' \n\n", input); return input; }).next(Info.c("topic == 'anthropic'", anthropicChain),Info.c("topic == 'langchain'", langchainChain),Info.c(generalChain)).build();AIMessageChunk chunk = chainActor.stream(fullChain, Map.of("question", "how do I use Anthropic?"));StringBuilder sb = new StringBuilder();while (chunk.getIterator().hasNext()) {sb.append(chunk.getIterator().next().getContent());System.out.println(sb);}
}

动态构建

主chain 调用 子chain 1 获取加工后的用户问题,子chain 1 根据用户输入问题是否带 对话历史,判断是调用子chain 2 根据历史修改用户问题,还是直接透传用户问题,主chain 根据最终问题,并添加 system 内容后,给出答案。

在这里插入图片描述

LangChain实现

from langchain_core.runnables import chain, RunnablePassthroughllm = OllamaLLM(model="llama3:8b")contextualize_instructions = """Convert the latest user question into a standalone question given the chat history. Don't answer the question, return the question and nothing else (no descriptive text)."""
contextualize_prompt = ChatPromptTemplate.from_messages([("system", contextualize_instructions),("placeholder", "{chat_history}"),("human", "{question}"),]
)
contextualize_question = contextualize_prompt | llm | StrOutputParser()@chain
def contextualize_if_needed(input_: dict):if input_.get("chat_history"):return contextualize_questionelse:return RunnablePassthrough() | itemgetter("question")@chain
def fake_retriever(input_: dict):return "egypt's population in 2024 is about 111 million"qa_instructions = ("""Answer the user question given the following context:\n\n{context}."""
)
qa_prompt = ChatPromptTemplate.from_messages([("system", qa_instructions), ("human", "{question}")]
)full_chain = (RunnablePassthrough.assign(question=contextualize_if_needed).assign(context=fake_retriever)| qa_prompt| llm| StrOutputParser()
)result = full_chain.stream({"question": "what about egypt","chat_history": [("human", "what's the population of indonesia"),("ai", "about 276 million"),],
})
for chunk in result:print(chunk, end="", flush=False)

J-LangChain实现
使用 flow组件 原生功能 .all() 实现执行 子chain 获取问题,并结合 system内容 给出答案的功能。

FlowInstance fullChain = chainActor.builder().all((iContextBus, isTimeout) -> Map.of("question", iContextBus.getResult(contextualizeIfNeeded.getFlowId()).toString(),"context", iContextBus.getResult("fakeRetriever")),Info.c(contextualizeIfNeeded),Info.c(input -> "egypt's population in 2024 is about 111 million").cAlias("fakeRetriever"))......
public void DynamicDemo() throws TimeoutException {ChatOllama llm = ChatOllama.builder().model("llama3:8b").build();String contextualizeInstructions = """Convert the latest user question into a standalone question given the chat history. Don't answer the question, return the question and nothing else (no descriptive text).""";BaseRunnable<ChatPromptValue, Object> contextualizePrompt = ChatPromptTemplate.fromMessages(List.of(Pair.of("system", contextualizeInstructions),Pair.of("placeholder", "${chatHistory}"),Pair.of("human", "${question}")));FlowInstance contextualizeQuestion = chainActor.builder().next(contextualizePrompt).next(llm).next(new StrOutputParser()).build();FlowInstance contextualizeIfNeeded = chainActor.builder().next(Info.c("chatHistory != null", new InvokeChain(contextualizeQuestion)),Info.c(input -> Map.of("question", ((Map<String, String>)input).get("question")))).build();String qaInstructions ="""Answer the user question given the following context:\n\n${context}.""";BaseRunnable<ChatPromptValue, Object>  qaPrompt = ChatPromptTemplate.fromMessages(List.of(Pair.of("system", qaInstructions),Pair.of("human", "${question}")));FlowInstance fullChain = chainActor.builder().all((iContextBus, isTimeout) -> Map.of("question", iContextBus.getResult(contextualizeIfNeeded.getFlowId()).toString(),"context", iContextBus.getResult("fakeRetriever")),Info.c(contextualizeIfNeeded),Info.c(input -> "egypt's population in 2024 is about 111 million").cAlias("fakeRetriever")).next(qaPrompt).next(input -> { System.out.printf("topic: '%s' \n\n", JsonUtil.toJson(input)); return input; }).next(llm).next(new StrOutputParser()).build();ChatGenerationChunk chunk = chainActor.stream(fullChain,Map.of("question", "what about egypt","chatHistory",List.of(Pair.of("human", "what's the population of indonesia"),Pair.of("ai", "about 276 million"))));StringBuilder sb = new StringBuilder();while (chunk.getIterator().hasNext()) {sb.append(chunk.getIterator().next().getText());System.out.println(sb);}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/892440.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【翻译】2025年华数杯国际赛数学建模题目+翻译pdf自取

保存至本地网盘 链接&#xff1a;https://pan.quark.cn/s/f82a1fa7ed87 提取码&#xff1a;6UUw 2025年“华数杯”国际大学生数学建模竞赛比赛时间于2025年1月11日&#xff08;周六&#xff09;06:00开始&#xff0c;至1月15日&#xff08;周三&#xff09;09:00结束&#xff…

C# GID+绘制不透明和半透明的线条

绘制线条时&#xff0c;必须将 Pen 对象传递给 DrawLine 类的 Graphics 方法。 Pen 构造函数的参数之一是 Color 对象。 若要绘制不透明的线条&#xff0c;请将颜色的 alpha 分量设置为 255。 若要绘制半透明的线条&#xff0c;请将 alpha 分量设置为从 1 到 254 的任何值。 在…

通过可穿戴外骨骼,以更灵活的方式操作你的机器人。

今天&#xff0c;我们将介绍一款专为控制 Mercury X1 和 Mercury B1 机械臂而设计的创新外骨骼。这种外骨骼以人类手臂的结构为蓝本&#xff0c;可实现直观和精确的控制。 开发这种外骨骼的动机源于人们对深度学习和机器学习等领域日益增长的兴趣。这些技术使机器人能够自主学习…

GaussDB分布式数据倾斜处理

常规数据倾斜巡检 在库中表个数少于1W的场景&#xff0c;直接使用倾斜视图查询当前库内所有表的数据倾斜情况 SELECT * FROM pgxc_get_table_skewness ORDER BY totalsize DESC;在库中表个数非常多&#xff08;至少大于1W&#xff09;的场景&#xff0c;因PGXC_GET_TABLE_SKEWN…

浅尝Appium自动化框架

浅尝Appium自动化框架 Appium自动化框架介绍Appium原理Appium使用安装平台驱动实战 坑 Appium自动化框架介绍 Appium 是一个开源的自动化测试框架&#xff0c;最初设计用于移动应用的测试&#xff0c;但现在它也扩展了对桌面端应用的支持。Appium 使得自动化测试变得更加简单&…

day38 tcp 并发 ,linux下的IO模型----IO多路复用

TCP 并发 由于tcp协议只能实现一对一的通信模式。为了实现一对多&#xff0c;有以下的的处理方式 1. 多进程 开销大 效率低 2. 多线程 创建线程需要耗时 3. 线程池 多线程模型创建线程耗时问题&#xff0c;提前创建 4. IO多路复用 在不创建进程和线程的前提下&#xff0c;对…

Kotlin | Android Provider 的实现案例

目标 使用 Android Room 实现持久化库。 代码 Kotlin 代码编写 DemoDatabase&#xff0c;在build生成 DemoDatabase_Impl 疑问 Provider的数据会存在设备吗&#xff1f; 内部存储: 当使用 Room 创建数据库&#xff08;如 DemoDatabase&#xff09;&#xff0c;数据库文件通常…

NFS服务

nfs文件系统 NFS:NetworkFileSystem网络文件系统&#xff0c;基于内核的文件系统。 服务安装 不固定端口启动&#xff0c;会注册到rpcbind&#xff08;固定端口&#xff09;服务上&#xff0c; 局域网适用[rootvm ~]# yum -y install nfs-utils # 依赖安装rpcbind [ro…

<C++学习>C++ 标准库(STD)的输入与输出(I/O)操作教程

C 的输入与输出主要通过标准库中的流类实现&#xff0c;包括标准输入流&#xff08;std::cin&#xff09;、标准输出流&#xff08;std::cout&#xff09;、标准错误流&#xff08;std::cerr&#xff09;和文件流&#xff08;std::ifstream 和 std::ofstream&#xff09;。以下…

maven多模块项目编译一直报Failure to find com.xxx.xxx:xxx-xxx-xxx:pom:1.0-SNAPSHOT in问题

工作中项目上因为多版本迭代&#xff0c;需要对不同迭代版本升级版本号&#xff0c;且因为项目工程本身是多模块结构&#xff0c;且依然多个其他模块工程。 在将工程中子模块的pom.xml中版本号使用变量引用父模块中定义的版本号时&#xff0c;一直报Failure to find com.xxx.x…

来自通义万相的创意加速器:AI 绘画创作

来自通义万相的创意加速器&#xff1a;AI 绘画创作 通义万相动手搭建“通义万相”部署方案资源准备对象存储OSS&#xff08;手动部署&#xff09;DashScope 模型服务灵积云服务器ECS&#xff08;手动部署&#xff09;一键部署ROS Web文生图艺术与设计创作广告与营销物料生成教育…

【Uniapp-Vue3】组合式API中的组件的生命周期函数(钩子函数)

在Uniapp中生命周期函数用得较多的是onMounted和onUnmounted。 一、onMounted函数 如果我们想要获得DOM元素&#xff0c;就需要给DOM标签上添加ref属性&#xff0c;并定义一个相同属性名的变量。 但是我们输出这个DOM元素为NULL 如果我们使用onMounted就能获得到DOM元素&…

Web 品质样式表

《Web 品质样式表》是一个重要的指南&#xff0c;旨在帮助开发者提升网站的整体质量和用户体验。以下是一些关键点&#xff1a; 避免使用 <font> 标签&#xff1a;应使用 CSS 来设置显示网页上的字体尺寸。使用 <font> 标签会增加文档的规模&#xff0c;且使每次改…

uniapp使用chooseLocation安卓篇

本文章全部以高德地图为例 代码 <view class"bottom"><button click"choose">定位</button> </view> choose() {uni.chooseLocation({success: function(res) {console.log(位置名称&#xff1a; res.name);console.log(详细地…

js:根据后端返回数据的最大值进行计算然后设置这个最大值为百分之百,其他的值除这个最大值

问&#xff1a; 现在tabData.value 接收到了后端返回的数据&#xff0c; [{text:人力,percentage&#xff1a;‘90’}&#xff0c;{text:物品,percentage&#xff1a;‘20’}&#xff0c;{text:物理,percentage&#xff1a;‘50’}&#xff0c;{text:服务,percentage&#xff…

设计一个利用事务特性可以阻塞线程的排他锁,并且通过注解和 AOP 来实现

设计思路&#xff1a; 利用数据库表记录锁标识&#xff1a;通过唯一标识符&#xff08;如方法名 参数&#xff09;&#xff0c;我们可以在数据库中插入一条记录&#xff0c;表示当前方法正在执行。这条记录需要记录插入时间。 注解&#xff1a;通过注解标识哪些方法需要加锁&a…

标定 3

标定场景与对应的方式 标定板标定主要应用场景: (1)无法获取到执行机构物理坐标值,比如相机固定,执行机构为传送带等 (2)相机存在畸变等非线性标定情况,需要进行畸变校正 (3)标定单像素精度 (4)获取两个相机之间的坐标系关系 标定板操作步骤: (1)确定好拍…

了解模2除法:原理与应用

模2除法&#xff0c;也被称为二进制除法或XOR除法&#xff0c;是一种在二进制数制下进行的特殊除法运算。与常规的十进制或其他进制的除法不同&#xff0c;模2除法使用异或&#xff08;XOR&#xff09;运算代替减法&#xff0c;并且不涉及进位或借位。这种除法运算在数字通信、…

基于 SSH 的任务调度系统

文末附有完整项目代码 在当今科技飞速发展的时代&#xff0c;任务调度系统的重要性日益凸显。本文将详细介绍一个基于 SSH&#xff08;SpringStruts2Hibernate&#xff09;的任务调度系统的设计与实现。 一、系统概述 本系统旨在改变传统人工任务调度方式&#xff0c;通过计算…

天童美语:如何培养孩子的音乐细胞

在孩子的成长旅程中&#xff0c;音乐不仅是美妙的旋律&#xff0c;更是情感表达和智力发展的重要媒介。培养孩子的音乐细胞不仅能增强他们的艺术修养&#xff0c;还能促进大脑发育&#xff0c;提高创造力和协调性。济南天童美语提供一些有效的方法&#xff0c;帮助家长激发孩子…