在LangChain的组件当中,Chat Models可以说跟LLMs占据着相同的“生态位”,它也是根据用户输入的提示内容,调用底层的大模型产生内容。与LLMs不同的是,LangChain的Chat Models主要有如下一些不同:
如前所述,Messages是Chat Models的主要输入类型,通过Messages我们可以给后端的大模型提供必要的角色和信息内容。在介绍Chat Models的使用前,先学习一下Messages的类型,便于后面的使用理解。
所有的Message都有两个属性:
根据这2个属性可以构造不同类型的Message。
Messages的主要类型见下表:
Message类型 | 作用说明 |
---|---|
HumanMessage | 表示“人”的消息,可以认为是使用者输入的信息,是对话的起点。 |
AIMessage | 表示模型的消息,是语言模型生成的响应消息,可以认为是对HumanMessage的回复。 |
SystemMessage | 表示给予语言模型的系统指令,告知大模型该以怎样的行为响应。一般用来设置语言模型的身份、任务和语气等。 并不是每个LangChain支持的大模型都支持这个类型。 |
FunctionMessage | 表示一个可执行函数或工具的调用结果。除了role和content,本类型消息还有一个name参数,用来传达用于生成此结果的函数名称。 |
ToolMessage | 与FunctionMessage类似,表示工具调用的结果。此类型的message携带tool_call_id参数表示生成该结果的工具id。 |
作为Runnable的子类,Chat Models的使用和LLMs大同小异,主要的不同就是构造Messages对象,如下面代码所示:
- from langchain_community.chat_models import ChatOllama
- from langchain_core.messages import SystemMessage, HumanMessage
-
- # 构造Messages对象,提供系统信息(SystemMessage)和用户信息(HumanMessage)。
- messages = [
- SystemMessage(content="You're a helpful assistant"),
- HumanMessage(content="What is the purpose of model regularization?"),
- ]
-
- # 使用的是ChatOllama类,而非Ollama
- chat = ChatOllama(model="llama3")
-
- # 返回的是AIMessage对象
- response = chat.invoke(messages)
-
- # 打印AIMessage对象的content内容
- print(response.content)
当传入messages给到Chat Model的invoke方法后,返回结果在AIMessage的response对象里。打印content的内容结果如下:
与前面介绍的LLMs直接返回str类型的结果不同,Chat Models输出的结果是Chat Message,因此,如果只想要大模型回答的结果内容,需要访问content字段。
所有实现了Runnable接口的Chat Models都默认支持ainvoke/batch/abatch/stream/astream方法。流式传输支持返回结果的iterator,这样可以用迭代的方式输出结果:
比如上面的代码调用invoke部分改成:
- for trunk in chat.stream(messages):
- print(trunk.content, end="", flush=True)
最终结果一致,只是输出是迭代的流式输出。
与自定义LLM类似,自定义Chat Model需要继承BaseChatModel,并实现方法:
还有一些可选接口方法:
下面定义一个自定义的Chat Model叫做MyCustomChatModel,为了简单示例,这里对任何输入都返回固定的字符串:
- from typing import Any, List, Optional
-
- from langchain_core.callbacks import (
- CallbackManagerForLLMRun,
- )
- from langchain_core.language_models import BaseChatModel
- from langchain_core.messages import BaseMessage, AIMessage
- from langchain_core.outputs import ChatGeneration, ChatResult
-
-
- class MyCustomChatModel(BaseChatModel):
- def _generate(
- self,
- messages: List[BaseMessage],
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> ChatResult:
- # 这里实现自己的生成逻辑,此处仅作举例所以输出固定字符串
- tokens = "I don't want to answer any question from you"
- message = AIMessage(
- content=tokens,
- additional_kwargs={}, # Used to add additional payload (e.g., function calling request)
- response_metadata={ # Use for response metadata
- "time_in_seconds": 3,
- },
- )
-
- generation = ChatGeneration(message=message)
- return ChatResult(generations=[generation])
-
- @property
- def _llm_type(self) -> str:
- return "my_custom_chat_model"
-
-
- # 使用自定义的Chat Model
- chat = MyCustomChatModel()
-
- response = chat.invoke("tell me a joke about bear")
- print(response.content)
结果打印如下:
在模型返回AIMessage中,还有一些额外的信息,模型提供商会将它们记录在AIMessage的response_metadata属性中。
使用很简单,如下直接调用ChatModel返回的AIMessage对象的response_metadata属性:
print(response.response_metadata)
在ChatOllama中返回如下(json格式化处理过):
{
"model": "llama3",
"created_at": "2024-06-19T13:02:40.297019706Z",
"message": {
"role": "assistant",
"content": ""
},
"done_reason": "stop",
"done": true,
"total_duration": 13890899022,
"load_duration": 7291480563,
"prompt_eval_count": 27,
"prompt_eval_duration": 124457000,
"eval_count": 355,
"eval_duration": 6327830000
}
不同提供商具体提供了哪些内容,需要查阅对应厂家的文档。通过response_metadata,有些厂家提供了Token使用的统计数据,有些提供了日志相关信息。
具体使用和LLMs类似,具体使用方法可以参看《LangChain入门学习笔记(四)—— Model I/O之LLMs》的缓存部分。