跳至主要內容

LangChain基础

pptg大约 3 分钟

主要模块

LangChain主要模块包括ModelPromptChainRetrievalAgentTool,在基础部分可以节省很多时间,但是对于Chain这块的LCEL写法,感觉完全没必要,自己封装反而更容易Debug。

1. Model

Model模块提供了对接不同大模型的功能,主要包括大模型LLMChatModel和向量化模型Embedding

1.1 LLM & CHatModel

LLM和ChatModel类似,但是随着技术的演进,基本上只用ChatModel就好了,ChtModel能更好地处理复杂交互、角色设定和上下文管理。

  • LLM是早期的模块,设计目的是用来做文本补全、文本生成,所以输入输出都是字符串格式。
  • ChatModel,设计目的是用来做多轮对话,输入输出都变成了结构化的消息列表。
from langchain.chat_models import ChatOpenAI
from langchain.schema import HumanMessage, SystemMessage

llm = ChatOpenAI(
    model="DeepSeek-V3-0324",
    base_url="xxx",
    api_key="xxx"
)

messages = [
    SystemMessage(content="你是AI助手,名叫多比"),
    HumanMessage(content="你好,请问你是谁")
]

res = llm.invoke(messages)

print(res.content)

# 输出
# 你好!我是多比,你的AI助手。随时为你提供帮助和解答问题!有什么可以帮你的吗?😊

这里的输出是Block的,想要打字机效果的话,可以使用stream

for chunk in llm.stream(messages):
    print(chunk.content, end="")
    
# 打字机输出
# 你好!我是多比,你的AI助手,随时为你提供帮助和解答问题。有什么我可以帮你的吗?😊

1.2 Embedding

Embedding模型用来将文本进行向量化。举个例子,“吃饭”和“用餐”在字面上是完全不同的,但是在语义上却非常相近。Embedding模型就是挖掘背后的语义信息,并映射为高维度向量,最后通过计算向量的相似度来判断语义上的相似性。

from langchain.embeddings import OpenAIEmbeddings

embd = OpenAIEmbeddings(
    openai_api_key="xxx", 
    openai_api_base="xxx"
)

res = embd.embed_query("你好")
print(res)

2. Prompt

LangChain的Prompt维护了占位{}、格式化的逻辑,能够动态的填充参数。最后,这个Prompt可以用于之前的Message列表,填充到LLM的上下文中。

from langchain.prompts import ChatPromptTemplate

template = "今天的日期是{date}"

prompt = ChatPromptTemplate.from_messages(
    ("system", template)
)

final_prompt = template.format(date="2000-01-01")
print(final_prompt)

# 今天的日期是2000-01-01

3. Chain

不建议使用,感觉有点过度封装,可以自己搓一个简单的就行了

from langchain_core.prompts import ChatPromptTemplate
from datetime import datetime, timezone

# 使用模板字符串的方式
prompt = ChatPromptTemplate.from_messages([
    ("system", "你是AI助手,名叫多比"),
    ("system", "当前时间: {time}"),
    ("human", "用户问题: {input}"),
])

def chain(input: str):
    format_messages = prompt.format_messages(
        time=str(datetime.now(timezone.utc)),
        input=input
    )
    print(format_messages)  #这里会看到占位符已经被替换了
    return llm.invoke(format_messages).content

4. Retrieval

Retrieval,也就是RAG中的R。这里会用到1.2中的Embedding模型,以及向量数据库,共同组成知识库

from langchain.document_loaders import TextLoader
# load
loader = TextLoader("data.txt")
documents = loader.load()

from langchain.text_splitter import CharacterTextSplitter
# chunk
text_splitter = CharacterTextSplitter(chunk_size=50, chunk_overlap=10)
docs = text_splitter.split_documents(documents)
for d in docs:
    print(d)
    
from langchain_community.embeddings import XinferenceEmbeddings
embeddings = XinferenceEmbeddings(
    server_url="http://172.16.160.4:9998",
    model_uid="bge-m3"
)

from langchain.vectorstores import Chroma
# 纯内存, just a test
db = Chroma.from_documents(
    documents=docs,
    embedding=embeddings,
    persist_directory=None
)

query = "LLM模型的关键技术"
docs = db.similarity_search(query, k=2)
print(docs[0].page_content)

# Q: LLM模型的关键技术
# A: 扩展、训练、能力引导、对齐微调、工具操作

5. Agent & Tool

LangChain给的了很多预定义的Agent和Tool,下面是一个查天气的demo。对于更细致的Agent,还是建议用LangGraph来做

from langchain.agents import Tool, initialize_agent, AgentType

import re

def weather(location: str):
    location = str(location).strip()
    location = re.sub(r'[\'"\n]', '', location)
    location = location.strip()
    
    if location == "北京":
        return f"{location}阴天,气温14度"
    elif location == "天津":
        return f"{location}晴天,气温21度"
    else:
        return f"无法获取'{location}'的天气信息,当前支持:北京、天津"

tools = [
    Tool(name="weather",func=weather,description="查询天气")
]

# ReAct模式, 还有很多模式可以在AgentType里看
agent = initialize_agent(
    tools=tools,
    llm=llm,
    agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
    verbose=True  # 打印过程
)

result = agent.run("北京和天津的天气怎么样")
print(result)

# 北京今天是阴天,气温14度;天津今天是晴天,气温21度。