Langchain中的消息
1.消息概述
目前基本所有的大模型API都与openai API兼容,具体来说请求和应答的格式与openai的保持一致,以deepseek为例(其他大模型仅仅是模型名不同),一个聊天请求的具体数据格式如下:
{
"model": "deepseek-chat",
"messages": [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Hello!"}
],
"stream": false
}
在请求数据中messages承载了用户和大模型交互的业务数据,messages列表可以很长,其中包括用户请求、大模型应答以及对大模型的人格设定。
在Langchain中的消息就是以上messages的具体实现,其中包括了大模型的输入和输出数据,携带与大模型交互时表示对话状态所需的内容和元数据。LangChain提供了一种标准消息类型,适用于所有大模型,从而确保无论调用使用何种大模型,对于调用者来说都是一样的。
一条消息由如下三部分构成:
1)role:表示消息的类型,共有四种,分别是user,system,assistant和tool
2)content:消息中的具体内容
3)metadata:消息的元数据,比如消息ID,词元使用情况等
2.调用大模型
下面说明一下如何调用大模型,首先初始化一个大模型:
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
model = 'qwen-plus',
api_key = "sk-*",
base_url = "https://dashscope.aliyuncs.com/compatible-mode/v1")
2.1直接调用
最简单的情况,直接调用大模型,比如:
response = llm.invoke("你是一个陕西的唐诗大家,请用陕西话改写送元二使安西").content
print(response)
此时,调用时传入的消息跟openai API的数据格式不同,但langchain在调用大模型时会自动修改为:
{
"model": "deepseek-chat",
"messages": [
{"role": "user", "content": "你是一个陕西的唐诗大家,请用陕西话改写送元二使安西"}
],
"stream": false
}
输出如下:
哎呀,元二老弟!你这就要走咧?唉,莫说这话,让咱老哥给你整一首送行的诗,用咱长安土话谝一谝,才带劲!
渭城朝雨浥轻尘,
客舍青青柳色新。
劝君更进一杯酒,
西出阳关无故人。咱用陕西话谝一遍:
渭城个早晨下咧场小雨,把土都沾住了,不扬片片;
客栈墙外头个柳树绿茵茵滴,嫩生生滴,刚发芽么!
老哥我再敬你一碗酒,你得喝了——
出了阳关往西去,再想寻个熟人谝个闲传,都没咧啊!唉,元二啊元二,路上慢些走,到了安西莫忘了给老哥捎个信儿。咱这酒可是从曲江池边老铺子打滴,一口下去,满嘴都是长安味儿!
2.2自己组织消息
根据openai API的消息格式,自己组装消息,再调用大模型,具体如下:
messages = [
{"role": "system", "content": "你是一个陕西的唐诗大家"},
{"role": "user", "content": "请用陕西话改写送元二使安西"},
]
response = llm.invoke(messages).content
print(response)
2.3使用langchain的消息
使用langchain中的系统的消息类组织请求数据,然后调用大模型,具体如下:
from langchain.messages import SystemMessage, HumanMessage
messages = [
SystemMessage("你是一个陕西的唐诗大家"),
HumanMessage("请用陕西话改写送元二使安西"),
]
response = llm.invoke(messages).contentprint(response)
3.消息详解
在openai API的role包括三种:user,assistant和system。分别表示用户输入、大模型应答和角色定位说明。langchian中于此对应的分别有三种的不同的消息类型:HumanMessage,AIMessage和SystemMessage,同时为了支持大模型的function calling,增加了一种消息类型ToolMessage,封装函数调用结果相关数据。
3.1SystemMessage
SystemMessage表示设定模型行为的初始指令集,可以用来定义模型角色、设定回复的强调,还可以对于应答的格式进行约束。
如下代码,设定模型为熟悉springcloud框架的Java专家,然后让他生成断路保护器的代码,具体如下:
messages = [
system_msg,
HumanMessage("如何创建一个短路保护器?")
]
response = llm.invoke(messages)
print(response.content)
输出为:
在 Spring Cloud 微服务架构中,短路保护(Circuit Breaker)通常使用 **Resilience4j** 或旧版的 **Hystrix**(已停更)。推荐使用 Resilience4j,它是轻量、函数式、高性能的容错库。
下面是一个使用 **Resilience4j + Spring Boot + OpenFeign** 的短路保护器示例:
---
### ✅ 1. 添加依赖(`pom.xml`)
```xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId>
</dependency>
```---
### ✅ 2. 启用 Feign 和 CircuitBreaker
```java
@SpringBootApplication
@EnableFeignClients
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
```---
### ✅ 3. 创建 Feign Client
```java
@FeignClient(name = "userClient", url = "https://api.example.com")
public interface UserClient {@GetMapping("/users/{id}")
String getUser(@PathVariable("id") Long id);
}
```---
### ✅ 4. 使用 `CircuitBreakerFactory` 包装调用
```java
@Service
public class UserService {@Autowired
private UserClient userClient;@Autowired
private CircuitBreakerFactory circuitBreakerFactory;public String getUserWithFallback(Long id) {
CircuitBreaker circuitBreaker = circuitBreakerFactory.create("userCB"); // 名称唯一return circuitBreaker.run(
() -> userClient.getUser(id),
throwable -> getFallback(id, throwable)
);
}private String getFallback(Long id, Throwable throwable) {
return "Fallback: User service is down (" + throwable.getMessage() + ")";
}
}
```---
### ✅ 5. 配置 `application.yml`
```yaml
resilience4j.circuitbreaker:
instances:
userCB:
failureRateThreshold: 50
minimumNumberOfCalls: 5
waitDurationInOpenState: 5s
slidingWindowSize: 10
```> 当失败率达到 50%(如 10 次中有 5 次失败),断路器进入 `OPEN` 状态,停止请求 5 秒后尝试恢复(半开状态)。
---
### ✅ 工作原理简述:
- **CLOSED**:正常调用。
- **OPEN**:失败过多,直接短路,返回 fallback。
- **HALF_OPEN**:等待期过后尝试恢复调用。---
### ✅ 可选:使用注解方式(更简洁)
引入 `@CircuitBreaker` 注解:
```java
@CircuitBreaker(name = "userCB", fallbackMethod = "getFallback")
public String getUser(Long id) {
return userClient.getUser(id);
}public String getFallback(Long id, CallNotPermittedException ex) {
return "Service unavailable, using fallback.";
}
```需确保开启注解支持(Spring Cloud CircuitBreaker 支持)。
---
### 总结
✅ 推荐组合:
**Spring Boot + OpenFeign + Resilience4j (via Spring Cloud CircuitBreaker)**优点:
- 轻量、易配置
- 支持熔断、降级、监控(集成 Micrometer)
- 官方推荐替代 Hystrix需要我加上监控(如 Prometheus + Grafana)示例吗?
如果不设定角色,让大模型完成同样的任务呢?
messages = [#把SystemMessage去掉
HumanMessage("如何创建一个短路保护器?")
]
response = llm.invoke(messages)
print(response.content)
输出结果肯定不如人意,具体如下:
创建一个短路保护器(Short-Circuit Protector)的目的是在电路发生短路时迅速切断电流,防止设备损坏或火灾。以下是几种常见且实用的方法来实现短路保护,适用于不同应用场景:
---
### 一、基本原理
短路是指电流绕过正常负载,直接从正极流向负极,导致电流急剧上升。短路保护器通过检测异常大电流并快速断开电路来实现保护。常用元件包括:
- 保险丝(Fuse)
- 断路器(Circuit Breaker)
- 自恢复保险丝(PPTC)
- 电子式保护电路(如使用MOSFET + 电流检测)---
### 二、简单方案:使用保险丝
**材料**:
- 保险丝(根据电路额定电流选择,例如1A、5A等)
- 保险丝座(可选)**步骤**:
1. 将保险丝串联在电源正极线路中。
2. 当电流超过保险丝额定值时,内部金属熔断,断开电路。
3. 短路排除后需更换保险丝。✅ 优点:成本低、可靠
❌ 缺点:一次性使用,需手动更换---
### 三、进阶方案:自恢复保险丝(PPTC)
**材料**:
- PPTC(聚合物正温度系数器件),如Polyswitch**连接方式**:
- 与保险丝一样,串联在主电路中。**工作原理**:
- 正常电流下电阻很小。
- 短路时电流过大 → 温度升高 → PPTC电阻急剧增大 → 切断电流。
- 故障排除后自动恢复导通。✅ 优点:可重复使用,适合消费电子产品
❌ 缺点:响应速度较慢,不适合高精度应用---
### 四、智能电子短路保护电路(推荐DIY)
使用电子元件构建一个可调、快速响应的保护电路。
#### 示例电路:基于MOSFET + 运放/比较器
**所需元件**:
- N沟道MOSFET(如IRF540N)——作为开关
- 电流检测电阻(低阻值,如0.1Ω/1W)
- 运算放大器或比较器(如LM358)
- 齐纳二极管或稳压源(参考电压)
- 继电器或驱动电路(可选)
- 电容、电阻若干#### 工作流程:
1. 电流流过检测电阻,产生压降(V = I × R)。
2. 放大该电压信号,送入比较器。
3. 比较器将采样电压与设定阈值比较。
4. 若超过阈值(表示短路),输出信号关闭MOSFET,切断电源。
5. 可加入延时或锁定机制防止误触发。#### 简化版本(带自锁保护):
```plaintext
电源+ → 电流检测电阻 → MOSFET漏极
↓
负载
↓
电源-
控制逻辑:
当检测到过流 → 触发三极管或比较器 → 关断MOSFET栅极电压 → 断开电路
```✅ 优点:响应快、可调节、可复位
❌ 缺点:设计复杂,需调试---
### 五、模块化解决方案(适合初学者)
使用现成的保护模块更安全便捷:
1. **电子保险丝模块**(eFuse Module)
2. **过流保护IC** 如:
- TI TPS2592xx(支持过流、过压保护)
- ON Semi NIS5110
- Maxim MAX1757x这些芯片集成检测、控制和保护功能,只需外围少量元件即可实现高性能短路保护。
---
### 六、注意事项
1. **匹配额定值**:保护器的额定电压/电流必须大于等于系统需求。
2. **响应时间**:短路应在几毫秒内被切断。
3. **散热设计**:大电流下检测电阻和MOSFET需良好散热。
4. **安全隔离**:高压系统需注意绝缘与隔离。
5. **测试验证**:可在低压小电流下模拟短路测试保护功能。---
### 总结:如何选择?
| 场景 | 推荐方案 |
|------|----------|
| 家用电器、简单电路 | 保险丝或PPTC |
| 可充电设备(如电池) | PPTC + 电压保护 |
| 工业/精密设备 | 电子保护电路或专用eFuse IC |
| DIY实验 | LM358 + MOSFET + 检测电阻 |---
如果你提供具体的应用场景(如:12V直流电源、电机驱动、锂电池供电等),我可以为你定制一个详细的电路图和元件清单。
3.2HumanMessage
HumanMessage代表用户的输入,可以是文本、图片、音频或者视频。还可以包含元数据,比如:
human_message = HumanMessage(
content="请解释一下薛定谔的猫!",
name="bob",
id="123",
)
response = llm.invoke([
human_message
]).content
print(response)
其中的name和id表示用户名和本消息的id,具体可以使用哪些元数据,需要查询对应的大模型文档。
3.3AIMessage
AIMessage是对调用大模型的输出结果封装,并且在langchain生态中使用。以下是直接调用大模型是的返回结果:
{
"choices": [
{
"message": {
"role": "assistant",
"content": "我是阿里云开发的一款超大规模语言模型,我叫通义千问。"
},
"finish_reason": "stop",
"index": 0,
"logprobs": null
}
],
"object": "chat.completion",
"usage": {
"prompt_tokens": 3019,
"completion_tokens": 104,
"total_tokens": 3123,
"prompt_tokens_details": {
"cached_tokens": 2048
}
},
"created": 1735120033,
"system_fingerprint": null,
"model": "qwen-plus",
"id": "chatcmpl-6ada9ed2-7f33-9de2-8bb0-78bd4035025a"
}
langchian基于以上标准应答封装AIMessage。
AIMessage可以包括多模态数据、工具调用数据和大模型提供商所提供的其他元数据,比如令牌使用情况。
以下代码输出大模型应答类型和数据:
response = llm.invoke("请简单解释一下黑暗森林法则,要求不超过100字")
print(type(response))
print(response)
输出如下:
<class 'langchain_core.messages.ai.AIMessage'>
content='黑暗森林法则是刘慈欣在《三体》中提出的宇宙文明生存理论:宇宙如黑暗森林,每个文明都是带枪的猎人,为自保必须隐藏自己,一旦发现其他文明,最安全的选择就是消灭对方,以防被先发制人。' additional_kwargs={'refusal': None} response_metadata={'token_usage': {'completion_tokens': 59, 'prompt_tokens': 22, 'total_tokens': 81, 'completion_tokens_details': None, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 0}}, 'model_provider': 'openai', 'model_name': 'qwen-plus', 'system_fingerprint': None, 'id': 'chatcmpl-3f07af6a-dfb6-4611-9add-39b86554aef4', 'finish_reason': 'stop', 'logprobs': None} id='lc_run--11ed3caf-6f5f-4ccb-85d5-28836c4c928f-0' usage_metadata={'input_tokens': 22, 'output_tokens': 59, 'total_tokens': 81, 'input_token_details': {'cache_read': 0}, 'output_token_details': {}}
3.4ToolMessage
ToolMessage与是调用工具的结果,与大模型的工具调用(function calling)紧密相关,大模型的工具调用(function calling)是指根据上下文和大模型绑定的工具集选择需要调用的工具及参数。这些信息包括在大模型返回的AIMessage中。以下示例说明了大模型的function calling调用过程。
以下代码中声明了一个简单的加法工具,当对大模型提出整数加法的问题时,大模型会选择加法工具,并返回对应的参数,具体代码如下:
from langchain.tools import tool
@tool
def add(a: int, b:int)->int:
'''Add two numbers'''
return a + b
tools = [add,]
model = llm.bind_tools(tools)
ai_message = model.invoke("计算100+99")
查看大模型的响应数据:
ai_message
输出如下:
AIMessage(content='', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 27, 'prompt_tokens': 161, 'total_tokens': 188, 'completion_tokens_details': None, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 0}}, 'model_provider': 'openai', 'model_name': 'qwen-plus', 'system_fingerprint': None, 'id': 'chatcmpl-7c6f01a6-03a1-4233-aab5-ab1b59206e4a', 'finish_reason': 'tool_calls', 'logprobs': None}, id='lc_run--2929ca49-979b-4e40-b44e-a93078fabde8-0', tool_calls=[{'name': 'add', 'args': {'a': 100, 'b': 99}, 'id': 'call_c872fc02b15f4285abf421', 'type': 'tool_call'}], usage_metadata={'input_tokens': 161, 'output_tokens': 27, 'total_tokens': 188, 'input_token_details': {'cache_read': 0}, 'output_token_details': {}})
可以看到大模型返回的是AIMessage,同时数据中包括tool_calls就是需要调用的工具信息,具体如下:
[{'name': 'add',
'args': {'a': 100, 'b': 99},
'id': 'call_c872fc02b15f4285abf421',
'type': 'tool_call'}]
调用工具,并生成ToolMessage,具体代码如下:
sum = add.invoke(ai_message.tool_calls[0]['args'])
tool_message = ToolMessage(
content=sum,
tool_call_id=ai_message.tool_calls[0]['id']
)
把前面的HumanMessage,AIMessage和ToolMessage组合后再次调用大模型:
messages = [
HumanMessage("计算100+99"),
ai_message,
tool_message]
response = model.invoke(messages)
response.content
大模型输出内容为:
100 + 99 的结果是 199。
4.消息内容说明
所有的消息类型都一个content属性,content没有强制类型要求,可以是字符串,可以是任意类型的数组,这是为了支持未遵循openai API格式的大模型而设计的。
同时angChain为文本、推理、引用、多模态数据、服务器端工具调用和其他消息内容提供了专用的内容类型。所有的消息类型还有一个content_blocks属性,content_blocks采用了明确的数据类型,实际是 content的另一种表示,content_blocks的类型包括text、reasoning、image、video、audio和file。
比如一个文本应答的content_blocks为:
[{'type': 'text',
'text': '哎呀,元二老哥,你又要走咧?这回可是要去那安西都护府啊!我这个陕西娃,给你用咱关中的腔调,把王维这首诗重新谝一谝:\n\n渭城朝雨浥轻尘,\n客舍青青柳色新。\n劝君更尽一杯酒,\n西出阳关无故人。\n\n咱陕西话咋说哩?听好咯——\n\n"渭城个早雨把土雾儿都压停当咧,\n驿站里头柳树绿茵茵个新鲜劲儿。\n老哥诶,再咥上这一杯烧酒,\n出了阳关那达,可就冇人跟你谝闲传咧!"\n\n哎呀,说得我都恓惶咧。你看这渭水边上,杨柳依依,就像咱陕西婆姨编的花环。这酒是凤翔的西凤酒,辣得很,香得很!元二老哥,你这一走,怕是要翻过千山万壑,穿过戈壁滩,那达连个熟人都冇得。要不...咱俩再咥一碗?让这酒暖暖心窝子!\n\n(抹了把眼角)你说这长安城里头,咱们常在曲江池畔吟诗作对,如今你要去那西域,叫我咋想你唻...'}]
