LangChain組件(一) - 基礎(chǔ)篇

LangChain內(nèi)部提供了很多標(biāo)準(zhǔn)的、可以擴(kuò)展的接口,以及集成了不少第三方工具,了解這些組件也是非常重要的,后面我們開發(fā)LangChain都需要使用到這些Component,下面我們介紹它們,后面會(huì)針對(duì)場(chǎng)景來介紹如何使用LangChain進(jìn)行開發(fā):

Chat models

第一次看到Chat models和LLMs有點(diǎn)搞不懂這兩個(gè)有什么區(qū)別,我理解Chat models是用來逐步替代LLMs的。
它的輸入是 messages,返回也是 messages(不是string)。支持為對(duì)話的消息賦予不同的roles,用來區(qū)分AI、users、system messages等。

不過為了能很好的替代LLMs,也支持接受strings作為輸入,內(nèi)部會(huì)將其轉(zhuǎn)化為HumanMessage。

from langchain_openai import ChatOpenAI

model = ChatOpenAI(model="gpt-4")

from langchain_core.messages import HumanMessage, SystemMessage

messages = [
    SystemMessage(content="Translate the following from English into Italian"),
    HumanMessage(content="hi!"),
]

model.invoke(messages)

LLMs

LLMs 接受string作為輸入,返回也是string。
其實(shí)目前通過LangChain的wrappers,也支持了接受message作為輸入。

from langchain_openai import OpenAI

llm = OpenAI()

question = "What NFL team won the Super Bowl in the year Justin Beiber was born?"

llm.invoke(question)

看的出來,和ChatModels的輸入類型,還是有區(qū)別的。

Messages

messages這個(gè)類型,無疑是非常的重要了,所有的messages都有幾個(gè)屬性需要注意:

  • role:描述WHO,saying了這個(gè)消息
  • content:消息的內(nèi)容
    • string:大部分的消息類型都是如此
    • diction 列表:用于多模態(tài)輸入,比如包括了input type,input location等
  • response_metadata:幫助我們更好的理解返回?cái)?shù)據(jù)類型

HumanMessage

表示用戶的輸入message。

AIMessage

表示model的消息,除了content屬性,這個(gè)消息也包括了response_metadata。
tool_calls:這個(gè)字段也是可能由AIMessage生成的,表示的是需要調(diào)用工具了。

  • name:tool的名稱
  • args:tool的參數(shù)
  • id:tool call的id

SystemMessage

其實(shí)是告訴model的角色,并非所有model支持。

FunctionMessage

function call的結(jié)果。除了rolecontent字段,還提供了name字段,告訴function的名字。

ToolMessage

表示的是tool call的結(jié)果。調(diào)用工具的時(shí)候,除了rolecontent,還會(huì)產(chǎn)生tool_call_id參數(shù)。

Prompt templates

用于將用戶的input、parameters,翻譯為instructions。
接受一個(gè)dictionary類型的input,每個(gè)key表示的是變量;輸出的是PromptValue,這個(gè)PromptValue可以傳給LLM、ChatModel,也可以轉(zhuǎn)為string、message。

我們來看幾種prompt templates

  • String PromptTemplates
    用于format一個(gè)string,通常用于簡(jiǎn)單的inputs。
from langchain_core.prompts import PromptTemplate

prompt_template = PromptTemplate.from_template("Tell me a joke about {topic}")

prompt_template.invoke({"topic": "cats"})
  • Chat PromptTemplates
    用于format一個(gè)messages列表,示例如下:
from langchain_core.prompts import ChatPromptTemplate

prompt_template = ChatPromptTemplate.from_messages([
    ("system", "You are a helpful assistant"),
    ("user", "Tell me a joke about {topic}")
])

prompt_template.invoke({"topic": "cats"})
  • MessagesPlaceholder
    這個(gè)也挺有用,主要用于將messages列表,添加到某個(gè)特別的地方。
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.messages import HumanMessage, AIMessage

prompt_template = ChatPromptTemplate.from_messages([
    ("system", "You are a helpful assistant"),
    MessagesPlaceholder("msgs")
])

prompt_template.invoke({"msgs": [HumanMessage(content="hi!"), AIMessage(content="ciao!")]})

有意思的是,也可以用ChatPromptTemplate來實(shí)現(xiàn)。

prompt_template = ChatPromptTemplate.from_messages([
    ("system", "You are a helpful assistant"),
    ("placeholder", "{msgs}") # <-- This is the changed part
])

Example selectors

有時(shí)候希望提供一些樣例,可以這么做:

from langchain.prompts.example_selector.base import BaseExampleSelector
from typing import Dict, List
import numpy as np

class CustomExampleSelector(BaseExampleSelector):    
    def __init__(self, examples: List[Dict[str, str]]):
        self.examples = examples
    
    def add_example(self, example: Dict[str, str]) -> None:
        """Add new example to store for a key."""
        self.examples.append(example)

    def select_examples(self, input_variables: Dict[str, str]) -> List[dict]:
        """Select which examples to use based on the inputs."""
        return np.random.choice(self.examples, size=2, replace=False)

examples = [
    {"foo": "1"},
    {"foo": "2"},
    {"foo": "3"}
]

# Initialize example selector.
example_selector = CustomExampleSelector(examples)

# Select examples
example_selector.select_examples({"foo": "foo"})
# -> array([{'foo': '2'}, {'foo': '3'}], dtype=object)

# Add new example to the set of examples
example_selector.add_example({"foo": "4"})
example_selector.examples
# -> [{'foo': '1'}, {'foo': '2'}, {'foo': '3'}, {'foo': '4'}]

# Select examples
example_selector.select_examples({"foo": "foo"})

Output parsers

指的是parsers,接收model的output,解析為更加結(jié)構(gòu)化的內(nèi)容。
越來越多的models,支持function/tool調(diào)用,建議優(yōu)先使用function/tool調(diào)用,而非output parser。

LangChain有很多的output parser,不過這里要解釋一些概念,再來說明一下有哪些output parser。

  • name:output parser 的名稱
  • streaming的支持:output parser是否支持streaming
  • 是否有format指令:output parser是否有format指令
  • 是否調(diào)用LLM:output parser是否調(diào)用了LLM,一般用于糾正一些錯(cuò)誤的格式
  • 輸入類型:期望的輸入類型。有一些functions需要message有具體的kwargs(關(guān)鍵字參數(shù))
  • 輸出類型:parser的輸出類型
  • 描述:對(duì)outputparser的補(bǔ)充性描述
Name Supports Streaming Has Format Instructions Call's LLM Input Type Output Type Desc
Json Y Y Str/Message JSON Object
XML Y Y Str/Message dict
CSV Y Y Str/Message List[str]
OutputFixing Y Str/Message
RetryWithError Y Str/Message
Pydantic Y Str/Message pydantic.BaseModel
YAML Y Str/Message pydantic.BaseModel
PandasDataFrame Y Str/Message dict
Enum Y Str/Message Enum
Datatime Y Str/Message datetime.datetime
Structured Y Str/Message Dict[str, str]

Chat history

我們知道LLM有時(shí)候是需要了解對(duì)話歷史的,這樣方便上下文對(duì)話。
對(duì)話系統(tǒng)需要能夠訪問到past messages

ChatHistory可以用來包裹c(diǎn)hain,會(huì)跟進(jìn)inputs、outputs,將消息加入到一個(gè)message database,后面作為模型的輸入。

from langchain_community.chat_message_histories import ChatMessageHistory
from langchain_core.chat_history import BaseChatMessageHistory
from langchain_core.runnables.history import RunnableWithMessageHistory

store = {}

def get_session_history(session_id: str) -> BaseChatMessageHistory:
    if session_id not in store:
        store[session_id] = ChatMessageHistory()
    return store[session_id]

conversational_rag_chain = RunnableWithMessageHistory(
    rag_chain,
    get_session_history,
    input_messages_key="input",
    history_messages_key="chat_history",
    output_messages_key="answer",
)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容