面向大模型的开发框架LangChain
这篇文章会带给你
- 如何使用 LangChain:一套在大模型能力上封装的工具框架
- 如何用几行代码实现一个复杂的 AI 应用
- 面向大模型的流程开发的过程抽象
文章目录
- 这篇文章会带给你
- 写在前面
- LangChain 的核心组件
- 文档(以 Python 版为例)
- 模型 I/O 封装
- 1.1 模型 API:LLM vs. ChatModel
- 1.1.1 OpenAI 模型封装
- 1.1.2 多轮对话 Session 封装
- 1.2 模型的输入与输出
- 1.2.1 Prompt 模板封装
- 1.2.2 从文件加载 Prompt 模板
- 1.3 结构化输出
- 1.3.1 直接输出 Pydantic 对象
- 1.3.2 输出指定格式的 JSON
- 1.3.3 使用 OutputParser
- 1.4 Function Calling
- 1.5、小结
- 二、数据连接封装
- 2.1 文档加载器:Document Loaders
- 2.2 文档处理器
- 2.2.1 TextSplitter
- 2.3、向量数据库与向量检索
- 2.4、小结
- 三、对话历史管理
- 3.1、历史记录的剪裁
- 3.2、过滤带标识的历史记录
- 四、Chain 和 LangChain Expression Language (LCEL)
- 4.1 Pipeline 式调用 PromptTemplate, LLM 和 OutputParser
- 4.2 用 LCEL 实现 RAG
- 4.3 用 LCEL 实现工厂模式
- 4.4 存储与管理对话历史
- 五、LangServe
- 5.1、Server 端
- 5.2、Client 端
- LangChain 与 LlamaIndex 的错位竞争
- 总结
写在前面
官网:https://www.langchain.com/
LangChain 也是一套面向大模型的开发框架(SDK)
LangChain 是 AGI 时代软件工程的一个探索和原型
学习 LangChain 要关注接口变更
LangChain 的核心组件
- 模型 I/O 封装
- LLMs:大语言模型
- Chat Models:一般基于 LLMs,但按对话结构重新封装
- PromptTemple:提示词模板
- OutputParser:解析输出
- 数据连接封装
- Document Loaders:各种格式文件的加载器
- Document Transformers:对文档的常用操作,如:split, filter, translate, extract metadata, etc
- Text Embedding Models:文本向量化表示,用于检索等操作(啥意思?别急,后面详细讲)
- Verctorstores: (面向检索的)向量的存储
- Retrievers: 向量的检索
- 对话历史管理
- 对话历史的存储、加载与剪裁
- 架构封装
- Chain:实现一个功能或者一系列顺序功能组合
- Agent:根据用户输入,自动规划执行步骤,自动选择每步需要的工具,最终完成用户指定的功能
- Tools:调用外部功能的函数,例如:调 google 搜索、文件 I/O、Linux Shell 等等
- Toolkits:操作某软件的一组工具集,例如:操作 DB、操作 Gmail 等等
- 回调
文档(以 Python 版为例)
- 功能模块:https://python.langchain.com/docs/get_started/introduction
- API 文档:https://api.python.langchain.com/en/latest/langchain_api_reference.html
- 三方组件集成:https://python.langchain.com/docs/integrations/platforms/
- 官方应用案例:https://python.langchain.com/docs/use_cases
- 调试部署等指导:https://python.langchain.com/docs/guides/debugging
划重点: 创建一个新的 conda 环境,langchain-learn,再开始下面的学习!
conda create -n langchain-learn python=3.10
模型 I/O 封装
把不同的模型,统一封装成一个接口,方便更换模型而不用重构代码。
1.1 模型 API:LLM vs. ChatModel
pip install --upgrade langchain
pip install --upgrade langchain-openai
pip install --upgrade langchain-community
1.1.1 OpenAI 模型封装
from langchain_openai import ChatOpenAI# 保证操作系统的环境变量里面配置好了OPENAI_API_KEY, OPENAI_BASE_URL
llm = ChatOpenAI(model="gpt-4o-mini") # 默认是gpt-3.5-turbo
response = llm.invoke("你是谁")
print(response.content)
我是一个人工智能助手,旨在回答问题和提供信息。如果你有任何问题或需要帮助的地方,随时可以问我!
1.1.2 多轮对话 Session 封装
from langchain.schema import (AIMessage, # 等价于OpenAI接口中的assistant roleHumanMessage, # 等价于OpenAI接口中的user roleSystemMessage # 等价于OpenAI接口中的system role
)messages = [SystemMessage(content="你是聚客AI研究院的课程助理。"),HumanMessage(content="我是学员,我叫大拿。"),AIMessage(content="欢迎!"),HumanMessage(content="我是谁")
]ret = llm.invoke(messages)print(ret.content)
你是大拿,一位学员。有什么我可以帮助你的吗?
划重点:通过模型封装,实现不同模型的统一接口调用
1.2 模型的输入与输出
1.2.1 Prompt 模板封装
- PromptTemplate 可以在模板中自定义变量
from langchain.prompts import PromptTemplatetemplate = PromptTemplate.from_template("给我讲个关于{subject}的笑话")
print("===Template===")
print(template)
print("===Prompt===")
print(template.format(subject='小明'))
=Template=
input_variables=[‘subject’] input_types={} partial_variables={} template=‘给我讲个关于{subject}的笑话’
=Prompt=
给我讲个关于小明的笑话
from langchain_openai import ChatOpenAI# 定义 LLM
llm = ChatOpenAI(model="gpt-4o-mini")
# 通过 Prompt 调用 LLM
ret = llm.invoke(template.format(subject='小明'))
# 打印输出
print(ret.content)
小明有一天去参加一个学校的科学展览。他看到有个同学在展示一台可以自动写字的机器人。小明觉得很神奇,就问同学:“这个机器人怎么能写字的?”
同学得意地回答:“因为它有一个超级智能的程序!”
小明想了想,摇了摇头说:“那我也要给我的机器人装一个超级智能的程序!”
同学好奇地问:“你打算怎么做?”
小明认真地说:“我打算给它装上‘懒’这个程序,这样它就可以帮我写作业了!”
同学忍不住笑了:“你这是在找借口嘛!”
小明得意地耸耸肩:“反正我只要告诉老师,是机器人写的!”
- ChatPromptTemplate 用模板表示的对话上下文
from langchain.prompts import (ChatPromptTemplate,HumanMessagePromptTemplate,SystemMessagePromptTemplate,
)
from langchain_openai import ChatOpenAItemplate = ChatPromptTemplate.from_messages([SystemMessagePromptTemplate.from_template("你是{product}的客服助手。你的名字叫{name}"),HumanMessagePromptTemplate.from_template("{query}"),]
)llm = ChatOpenAI(model="gpt-4o-mini")
prompt = template.format_messages(product="聚客AI研究院",name="大吉",query="你是谁"
)print(prompt)ret = llm.invoke(prompt)print(ret.content)
[SystemMessage(content=‘你是聚客AI研究院的客服助手。你的名字叫大吉’, additional_kwargs={}, response_metadata={}), HumanMessage(content=‘你是谁’, additional_kwargs={}, response_metadata={})]
我是大吉,聚客AI研究院的客服助手。很高兴为您提供帮助!请问有什么我可以为您做的呢?
- MessagesPlaceholder 把多轮对话变成模板
from langchain.prompts import (ChatPromptTemplate,HumanMessagePromptTemplate,MessagesPlaceholder,
)human_prompt = "Translate your answer to {language}."
human_message_template = HumanMessagePromptTemplate.from_template(human_prompt)chat_prompt = ChatPromptTemplate.from_messages(# variable_name 是 message placeholder 在模板中的变量名# 用于在赋值时使用[MessagesPlaceholder("history"), human_message_template]
)
from langchain_core.messages import AIMessage, HumanMessagehuman_message = HumanMessage(content="Who is Elon Musk?")
ai_message = AIMessage(content="Elon Musk is a billionaire entrepreneur, inventor, and industrial designer"
)messages = chat_prompt.format_prompt(# 对 "history" 和 "language" 赋值history=[human_message, ai_message], language="中文"
)print(messages.to_messages())
[HumanMessage(content=‘Who is Elon Musk?’, additional_kwargs={}, response_metadata={}), AIMessage(content=‘Elon Musk is a billionaire entrepreneur, inventor, and industrial designer’, additional_kwargs={}, response_metadata={}), HumanMessage(content=‘Translate your answer to 中文.’, additional_kwargs={}, response_metadata={})]
result = llm.invoke(messages)
print(result.content)
埃隆·马斯克(Elon Musk)是一位亿万富翁企业家、发明家和工业设计师。
划重点:把Prompt模板看作带有参数的函数
1.2.2 从文件加载 Prompt 模板
from langchain.prompts import PromptTemplatetemplate = PromptTemplate.from_file("example_prompt_template.txt")
print("===Template===")
print(template)
print("===Prompt===")
print(template.format(topic='黑色幽默'))
=Template=
input_variables=[‘topic’] input_types={} partial_variables={} template=‘举一个关于{topic}的例子’
=Prompt=
举一个关于黑色幽默的例子
1.3 结构化输出
1.3.1 直接输出 Pydantic 对象
from pydantic import BaseModel, Field# 定义你的输出对象
class Date(BaseModel):year: int = Field(description="Year")month: int = Field(description="Month")day: int = Field(description="Day")era: str = Field(description="BC or AD")
from langchain.prompts import PromptTemplate, ChatPromptTemplate, HumanMessagePromptTemplate
from langchain_openai import ChatOpenAIfrom langchain_core.output_parsers import PydanticOutputParsermodel_name = 'gpt-4o-mini'
temperature = 0
llm = ChatOpenAI(model_name=model_name, temperature=temperature)# 定义结构化输出的模型
structured_llm = llm.with_structured_output(Date)template = """提取用户输入中的日期。
用户输入:
{query}"""prompt = PromptTemplate(template=template,
)query = "2024年十二月23日天气晴..."
input_prompt = prompt.format_prompt(query=query)structured_llm.invoke(input_prompt)
Date(year=2024, month=12, day=23, era=‘AD’)
1.3.2 输出指定格式的 JSON
json_schema = {"title": "Date","description": "Formated date expression","type": "object","properties": {"year": {"type": "integer","description": "year, YYYY",},"month": {"type": "integer","description": "month, MM",},"day": {"type": "integer","description": "day, DD",},"era": {"type": "string","description": "BC or AD",},},
}
structured_llm = llm.with_structured_output(json_schema)structured_llm.invoke(input_prompt)
{‘day’: 23, ‘month’: 12, ‘year’: 2024}
1.3.3 使用 OutputParser
OutputParser 可以按指定格式解析模型的输出
from langchain_core.output_parsers import JsonOutputParserparser = JsonOutputParser(pydantic_object=Date)prompt = PromptTemplate(template="提取用户输入中的日期。\n用户输入:{query}\n{format_instructions}",input_variables=["query"],partial_variables={"format_instructions": parser.get_format_instructions()},
)input_prompt = prompt.format_prompt(query=query)
output = llm.invoke(input_prompt)
print("原始输出:\n"+output.content)print("\n解析后:")
parser.invoke(output)
原始输出:
{"year": 2024, "month": 12, "day": 23, "era": "AD"}
解析后:
{‘year’: 2024, ‘month’: 12, ‘day’: 23, ‘era’: ‘AD’}
也可以用 PydanticOutputParser
from langchain_core.output_parsers import PydanticOutputParserparser = PydanticOutputParser(pydantic_object=Date)input_prompt = prompt.format_prompt(query=query)
output = llm.invoke(input_prompt)
print("原始输出:\n"+output.content)print("\n解析后:")
parser.invoke(output)
原始输出:
{"year": 2024,"month": 12,"day": 23,"era": "AD"
}
解析后:
Date(year=2024, month=12, day=23, era=‘AD’)
OutputFixingParser 利用大模型做格式自动纠错
from langchain.output_parsers import OutputFixingParsernew_parser = OutputFixingParser.from_llm(parser=parser, llm=ChatOpenAI(model="gpt-4o"))bad_output = output.content.replace("4","四")
print("PydanticOutputParser:")
try:parser.invoke(bad_output)
except Exception as e:print(e)print("OutputFixingParser:")
new_parser.invoke(bad_output)
PydanticOutputParser:
Invalid json output: ```json
{
“year”: 202四,
“month”: 12,
“day”: 23,
“era”: “AD”
}
For troubleshooting, visit: https://python.langchain.com/docs/troubleshooting/errors/OUTPUT_PARSING_FAILURE
OutputFixingParser:
Date(year=2024, month=12, day=23, era=‘AD’)
1.4 Function Calling
from langchain_core.tools import tool@tool
def add(a: int, b: int) -> int:"""Add two integers.Args:a: First integerb: Second integer"""return a + b@tool
def multiply(a: int, b: int) -> int:"""Multiply two integers.Args:a: First integerb: Second integer"""return a * b
import jsonllm_with_tools = llm.bind_tools([add, multiply])query = "3的4倍是多少?"
messages = [HumanMessage(query)]output = llm_with_tools.invoke(messages)print(json.dumps(output.tool_calls, indent=4))
[
{
“name”: “multiply”,
“args”: {
“a”: 3,
“b”: 4
},
“id”: “call_V6lxABmx12g6lIgT8WMUtexM”,
“type”: “tool_call”
}
]
回传 Funtion Call 的结果
messages.append(output)available_tools = {"add": add, "multiply": multiply}for tool_call in output.tool_calls:selected_tool = available_tools[tool_call["name"].lower()]tool_msg = selected_tool.invoke(tool_call)messages.append(tool_msg)new_output = llm_with_tools.invoke(messages)
for message in messages:print(json.dumps(message.dict(), indent=4, ensure_ascii=False))
print(new_output.content)
{
“content”: “3的4倍是多少?”,
“additional_kwargs”: {},
“response_metadata”: {},
“type”: “human”,
“name”: null,
“id”: null,
“example”: false
}
{
“content”: “”,
“additional_kwargs”: {
“tool_calls”: [
{
“id”: “call_V6lxABmx12g6lIgT8WMUtexM”,
“function”: {
“arguments”: “{“a”:3,“b”:4}”,
“name”: “multiply”
},
“type”: “function”
}
],
“refusal”: null
},
“response_metadata”: {
“token_usage”: {
“completion_tokens”: 18,
“prompt_tokens”: 97,
“total_tokens”: 115,
“completion_tokens_details”: {
“accepted_prediction_tokens”: 0,
“audio_tokens”: 0,
“reasoning_tokens”: 0,
“rejected_prediction_tokens”: 0
},
“prompt_tokens_details”: {
“audio_tokens”: 0,
“cached_tokens”: 0
}
},
“model_name”: “gpt-4o-mini-2024-07-18”,
“system_fingerprint”: “fp_0aa8d3e20b”,
“finish_reason”: “tool_calls”,
“logprobs”: null
},
“type”: “ai”,
“name”: null,
“id”: “run-d25ca9ee-50b1-4848-a79e-42e58803fc7a-0”,
“example”: false,
“tool_calls”: [
{
“name”: “multiply”,
“args”: {
“a”: 3,
“b”: 4
},
“id”: “call_V6lxABmx12g6lIgT8WMUtexM”,
“type”: “tool_call”
}
],
“invalid_tool_calls”: [],
“usage_metadata”: {
“input_tokens”: 97,
“output_tokens”: 18,
“total_tokens”: 115,
“input_token_details”: {
“audio”: 0,
“cache_read”: 0
},
“output_token_details”: {
“audio”: 0,
“reasoning”: 0
}
}
}
{
“content”: “12”,
“additional_kwargs”: {},
“response_metadata”: {},
“type”: “tool”,
“name”: “multiply”,
“id”: null,
“tool_call_id”: “call_V6lxABmx12g6lIgT8WMUtexM”,
“artifact”: null,
“status”: “success”
}
3的4倍是12。
C:\Users\Administrator\AppData\Local\Temp\ipykernel_16608\2298449061.py:12: PydanticDeprecatedSince20: The
dict
method is deprecated; usemodel_dump
instead. Deprecated in Pydantic V2.0 to be removed in V3.0. See Pydantic V2 Migration Guide at https://errors.pydantic.dev/2.10/migration/
print(json.dumps(message.dict(), indent=4, ensure_ascii=False))
1.5、小结
- LangChain 统一封装了各种模型的调用接口,包括补全型和对话型两种
- LangChain 提供了 PromptTemplate 类,可以自定义带变量的模板
- LangChain 提供了一些列输出解析器,用于将大模型的输出解析成结构化对象
- LangChain 提供了 Function Calling 的封装
- 上述模型属于 LangChain 中较为实用的部分
二、数据连接封装
2.1 文档加载器:Document Loaders
pip install pymupdf
from langchain_community.document_loaders import PyMuPDFLoaderloader = PyMuPDFLoader("llama2.pdf")
pages = loader.load_and_split()print(pages[0].page_content)
Llama 2: Open Foundation and Fine-Tuned Chat Models
Hugo Touvron∗
Louis Martin†
Kevin Stone†
Peter Albert Amjad Almahairi Yasmine Babaei Nikolay Bashlykov Soumya Batra
Prajjwal Bhargava Shruti Bhosale Dan Bikel Lukas Blecher Cristian Canton Ferrer Moya Chen
Guillem Cucurull David Esiobu Jude Fernandes Jeremy Fu Wenyin Fu Brian Fuller
Cynthia Gao Vedanuj Goswami Naman Goyal Anthony Hartshorn Saghar Hosseini Rui Hou
Hakan Inan Marcin Kardas Viktor Kerkez Madian Khabsa Isabel Kloumann Artem Korenev
Punit Singh Koura Marie-Anne Lachaux Thibaut Lavril Jenya Lee Diana Liskovich
Yinghai Lu Yuning Mao Xavier Martinet Todor Mihaylov Pushkar Mishra
Igor Molybog Yixin Nie Andrew Poulton Jeremy Reizenstein Rashi Rungta Kalyan Saladi
Alan Schelten Ruan Silva Eric Michael Smith Ranjan Subramanian Xiaoqing Ellen Tan Binh Tang
Ross Taylor Adina Williams Jian Xiang Kuan Puxin Xu Zheng Yan Iliyan Zarov Yuchen Zhang
Angela Fan Melanie Kambadur Sharan Narang Aurelien Rodriguez Robert Stojnic
Sergey Edunov
Thomas Scialom∗
GenAI, Meta
Abstract
In this work, we develop and release Llama 2, a collection of pretrained and fine-tuned
large language models (LLMs) ranging in scale from 7 billion to 70 billion parameters.
Our fine-tuned LLMs, called Llama 2-Chat, are optimized for dialogue use cases. Our
models outperform open-source chat models on most benchmarks we tested, and based on
our human evaluations for helpfulness and safety, may be a suitable substitute for closed-
source models. We provide a detailed description of our approach to fine-tuning and safety
improvements of Llama 2-Chat in order to enable the community to build on our work and
contribute to the responsible development of LLMs.
∗Equal contribution, corresponding authors: {tscialom, htouvron}@meta.com
†Second author
Contributions for all the authors can be found in Section A.1.
arXiv:2307.09288v2 [cs.CL] 19 Jul 2023
2.2 文档处理器
2.2.1 TextSplitter
pip install --upgrade langchain-text-splitters
from langchain_text_splitters import RecursiveCharacterTextSplitter# 简单的文本内容切割
text_splitter = RecursiveCharacterTextSplitter(chunk_size=200,chunk_overlap=100, length_function=len,add_start_index=True,
)paragraphs = text_splitter.create_documents([pages[0].page_content])
for para in paragraphs:print(para.page_content)print('-------')
Llama 2: Open Foundation and Fine-Tuned Chat Models
Hugo Touvron∗
Louis Martin†
Kevin Stone†
Peter Albert Amjad Almahairi Yasmine Babaei Nikolay Bashlykov Soumya Batra
Kevin Stone†
Peter Albert Amjad Almahairi Yasmine Babaei Nikolay Bashlykov Soumya Batra
Prajjwal Bhargava Shruti Bhosale Dan Bikel Lukas Blecher Cristian Canton Ferrer Moya Chen
Prajjwal Bhargava Shruti Bhosale Dan Bikel Lukas Blecher Cristian Canton Ferrer Moya Chen
Guillem Cucurull David Esiobu Jude Fernandes Jeremy Fu Wenyin Fu Brian Fuller
Guillem Cucurull David Esiobu Jude Fernandes Jeremy Fu Wenyin Fu Brian Fuller
Cynthia Gao Vedanuj Goswami Naman Goyal Anthony Hartshorn Saghar Hosseini Rui Hou
Cynthia Gao Vedanuj Goswami Naman Goyal Anthony Hartshorn Saghar Hosseini Rui Hou
Hakan Inan Marcin Kardas Viktor Kerkez Madian Khabsa Isabel Kloumann Artem Korenev
Hakan Inan Marcin Kardas Viktor Kerkez Madian Khabsa Isabel Kloumann Artem Korenev
Punit Singh Koura Marie-Anne Lachaux Thibaut Lavril Jenya Lee Diana Liskovich
Punit Singh Koura Marie-Anne Lachaux Thibaut Lavril Jenya Lee Diana Liskovich
Yinghai Lu Yuning Mao Xavier Martinet Todor Mihaylov Pushkar Mishra
Yinghai Lu Yuning Mao Xavier Martinet Todor Mihaylov Pushkar Mishra
Igor Molybog Yixin Nie Andrew Poulton Jeremy Reizenstein Rashi Rungta Kalyan Saladi
Igor Molybog Yixin Nie Andrew Poulton Jeremy Reizenstein Rashi Rungta Kalyan Saladi
Alan Schelten Ruan Silva Eric Michael Smith Ranjan Subramanian Xiaoqing Ellen Tan Binh Tang
Alan Schelten Ruan Silva Eric Michael Smith Ranjan Subramanian Xiaoqing Ellen Tan Binh Tang
Ross Taylor Adina Williams Jian Xiang Kuan Puxin Xu Zheng Yan Iliyan Zarov Yuchen Zhang
Ross Taylor Adina Williams Jian Xiang Kuan Puxin Xu Zheng Yan Iliyan Zarov Yuchen Zhang
Angela Fan Melanie Kambadur Sharan Narang Aurelien Rodriguez Robert Stojnic
Sergey Edunov
Thomas Scialom∗
Sergey Edunov
Thomas Scialom∗
GenAI, Meta
Abstract
In this work, we develop and release Llama 2, a collection of pretrained and fine-tuned
Abstract
In this work, we develop and release Llama 2, a collection of pretrained and fine-tuned
large language models (LLMs) ranging in scale from 7 billion to 70 billion parameters.
large language models (LLMs) ranging in scale from 7 billion to 70 billion parameters.
Our fine-tuned LLMs, called Llama 2-Chat, are optimized for dialogue use cases. Our
Our fine-tuned LLMs, called Llama 2-Chat, are optimized for dialogue use cases. Our
models outperform open-source chat models on most benchmarks we tested, and based on
models outperform open-source chat models on most benchmarks we tested, and based on
our human evaluations for helpfulness and safety, may be a suitable substitute for closed-
our human evaluations for helpfulness and safety, may be a suitable substitute for closed-
source models. We provide a detailed description of our approach to fine-tuning and safety
source models. We provide a detailed description of our approach to fine-tuning and safety
improvements of Llama 2-Chat in order to enable the community to build on our work and
improvements of Llama 2-Chat in order to enable the community to build on our work and
contribute to the responsible development of LLMs.
contribute to the responsible development of LLMs.
∗Equal contribution, corresponding authors: {tscialom, htouvron}@meta.com
†Second author
∗Equal contribution, corresponding authors: {tscialom, htouvron}@meta.com
†Second author
Contributions for all the authors can be found in Section A.1.
arXiv:2307.09288v2 [cs.CL] 19 Jul 2023
类似 LlamaIndex,LangChain 也提供了丰富的 Document Loaders 和 Text Splitters。
2.3、向量数据库与向量检索
conda install -c pytorch faiss-cpu
from langchain_openai import OpenAIEmbeddings
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import FAISS
from langchain_openai import ChatOpenAI
from langchain_community.document_loaders import PyMuPDFLoader# 加载文档
loader = PyMuPDFLoader("llama2.pdf")
pages = loader.load_and_split()# 文档切分
text_splitter = RecursiveCharacterTextSplitter(chunk_size=300,chunk_overlap=100,length_function=len,add_start_index=True,
)texts = text_splitter.create_documents([page.page_content for page in pages[:4]]
)# 灌库
embeddings = OpenAIEmbeddings(model="text-embedding-ada-002")
db = FAISS.from_documents(texts, embeddings)# 检索 top-3 结果
retriever = db.as_retriever(search_kwargs={"k": 3})docs = retriever.invoke("llama2有多少参数")for doc in docs:print(doc.page_content)print("----")
but are not releasing.§
2. Llama 2-Chat, a fine-tuned version of Llama 2 that is optimized for dialogue use cases. We release
variants of this model with 7B, 13B, and 70B parameters as well.
We believe that the open release of LLMs, when done safely, will be a net benefit to society. Like all LLMs,
Llama 2-Chat, at scales up to 70B parameters. On the series of helpfulness and safety benchmarks we tested,
Llama 2-Chat models generally perform better than existing open-source models. They also appear to
large language models (LLMs) ranging in scale from 7 billion to 70 billion parameters.
Our fine-tuned LLMs, called Llama 2-Chat, are optimized for dialogue use cases. Our
models outperform open-source chat models on most benchmarks we tested, and based on
更多的三方检索组件链接,参考:https://python.langchain.com/v0.3/docs/integrations/vectorstores/
2.4、小结
- 文档处理部分,建议在实际应用中详细测试后使用
- 与向量数据库的链接部分本质是接口封装,向量数据库需要自己选型
三、对话历史管理
3.1、历史记录的剪裁
from langchain_core.messages import (AIMessage,HumanMessage,SystemMessage,trim_messages,
)
from langchain_openai import ChatOpenAImessages = [SystemMessage("you're a good assistant, you always respond with a joke."),HumanMessage("i wonder why it's called langchain"),AIMessage('Well, I guess they thought "WordRope" and "SentenceString" just didn\'t have the same ring to it!'),HumanMessage("and who is harrison chasing anyways"),AIMessage("Hmmm let me think.\n\nWhy, he's probably chasing after the last cup of coffee in the office!"),HumanMessage("what do you call a speechless parrot"),
]trim_messages(messages,max_tokens=45,strategy="last",token_counter=ChatOpenAI(model="gpt-4o-mini"),
)
[AIMessage(content=“Hmmm let me think.\n\nWhy, he’s probably chasing after the last cup of coffee in the office!”, additional_kwargs={}, response_metadata={}),
HumanMessage(content=‘what do you call a speechless parrot’, additional_kwargs={}, response_metadata={})]
#保留 system prompt
trim_messages(
messages,
max_tokens=45,
strategy=“last”,
token_counter=ChatOpenAI(model=“gpt-4o-mini”),
include_system=True,
allow_partial=True,
)
[SystemMessage(content=“you’re a good assistant, you always respond with a joke.”, additional_kwargs={}, response_metadata={}),
HumanMessage(content=‘what do you call a speechless parrot’, additional_kwargs={}, response_metadata={})]
3.2、过滤带标识的历史记录
from langchain_core.messages import (AIMessage,HumanMessage,SystemMessage,filter_messages,
)messages = [SystemMessage("you are a good assistant", id="1"),HumanMessage("example input", id="2", name="example_user"),AIMessage("example output", id="3", name="example_assistant"),HumanMessage("real input", id="4", name="bob"),AIMessage("real output", id="5", name="alice"),
]filter_messages(messages, include_types="human")
[HumanMessage(content=‘example input’, additional_kwargs={}, response_metadata={}, name=‘example_user’, id=‘2’),
HumanMessage(content=‘real input’, additional_kwargs={}, response_metadata={}, name=‘bob’, id=‘4’)]
filter_messages(messages, exclude_names=["example_user", "example_assistant"])
[SystemMessage(content=‘you are a good assistant’, additional_kwargs={}, response_metadata={}, id=‘1’),
HumanMessage(content=‘real input’, additional_kwargs={}, response_metadata={}, name=‘bob’, id=‘4’),
AIMessage(content=‘real output’, additional_kwargs={}, response_metadata={}, name=‘alice’, id=‘5’)]
filter_messages(messages, include_types=[HumanMessage, AIMessage], exclude_ids=["3"])
[HumanMessage(content=‘example input’, additional_kwargs={}, response_metadata={}, name=‘example_user’, id=‘2’),
HumanMessage(content=‘real input’, additional_kwargs={}, response_metadata={}, name=‘bob’, id=‘4’),
AIMessage(content=‘real output’, additional_kwargs={}, response_metadata={}, name=‘alice’, id=‘5’)]
四、Chain 和 LangChain Expression Language (LCEL)
LangChain Expression Language(LCEL)是一种声明式语言,可轻松组合不同的调用顺序构成 Chain。LCEL 自创立之初就被设计为能够支持将原型投入生产环境,无需代码更改,从最简单的“提示+LLM”链到最复杂的链(已有用户成功在生产环境中运行包含数百个步骤的 LCEL Chain)。
LCEL 的一些亮点包括:
-
流支持:使用 LCEL 构建 Chain 时,你可以获得最佳的首个令牌时间(即从输出开始到首批输出生成的时间)。对于某些 Chain,这意味着可以直接从 LLM 流式传输令牌到流输出解析器,从而以与 LLM 提供商输出原始令牌相同的速率获得解析后的、增量的输出。
-
异步支持:任何使用 LCEL 构建的链条都可以通过同步 API(例如,在 Jupyter 笔记本中进行原型设计时)和异步 API(例如,在 LangServe 服务器中)调用。这使得相同的代码可用于原型设计和生产环境,具有出色的性能,并能够在同一服务器中处理多个并发请求。
-
优化的并行执行:当你的 LCEL 链条有可以并行执行的步骤时(例如,从多个检索器中获取文档),我们会自动执行,无论是在同步还是异步接口中,以实现最小的延迟。
-
重试和回退:为 LCEL 链的任何部分配置重试和回退。这是使链在规模上更可靠的绝佳方式。目前我们正在添加重试/回退的流媒体支持,因此你可以在不增加任何延迟成本的情况下获得增加的可靠性。
-
访问中间结果:对于更复杂的链条,访问在最终输出产生之前的中间步骤的结果通常非常有用。这可以用于让最终用户知道正在发生一些事情,甚至仅用于调试链条。你可以流式传输中间结果,并且在每个 LangServe 服务器上都可用。
-
输入和输出模式:输入和输出模式为每个 LCEL 链提供了从链的结构推断出的 Pydantic 和 JSONSchema 模式。这可以用于输入和输出的验证,是 LangServe 的一个组成部分。
-
无缝 LangSmith 跟踪集成:随着链条变得越来越复杂,理解每一步发生了什么变得越来越重要。通过 LCEL,所有步骤都自动记录到 LangSmith,以实现最大的可观察性和可调试性。
-
无缝 LangServe 部署集成:任何使用 LCEL 创建的链都可以轻松地使用 LangServe 进行部署。
原文:https://python.langchain.com/docs/expression_language/
4.1 Pipeline 式调用 PromptTemplate, LLM 和 OutputParser
from langchain_openai import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough
from pydantic import BaseModel, Field, validator
from typing import List, Dict, Optional
from enum import Enum
import json
# 输出结构
class SortEnum(str, Enum):data = 'data'price = 'price'class OrderingEnum(str, Enum):ascend = 'ascend'descend = 'descend'class Semantics(BaseModel):name: Optional[str] = Field(description="流量包名称", default=None)price_lower: Optional[int] = Field(description="价格下限", default=None)price_upper: Optional[int] = Field(description="价格上限", default=None)data_lower: Optional[int] = Field(description="流量下限", default=None)data_upper: Optional[int] = Field(description="流量上限", default=None)sort_by: Optional[SortEnum] = Field(description="按价格或流量排序", default=None)ordering: Optional[OrderingEnum] = Field(description="升序或降序排列", default=None)# Prompt 模板
prompt = ChatPromptTemplate.from_messages([("system", "你是一个语义解析器。你的任务是将用户的输入解析成JSON表示。不要回答用户的问题。"),("human", "{text}"),]
)# 模型
llm = ChatOpenAI(model="gpt-4o", temperature=0)structured_llm = llm.with_structured_output(Semantics)# LCEL 表达式
runnable = ({"text": RunnablePassthrough()} | prompt | structured_llm
)# 直接运行
ret = runnable.invoke("不超过100元的流量大的套餐有哪些")
print(json.dumps(ret.dict(),indent = 4,ensure_ascii=False)
)
{
“name”: null,
“price_lower”: null,
“price_upper”: 100,
“data_lower”: null,
“data_upper”: null,
“sort_by”: “data”,
“ordering”: “descend”
}
C:\Users\Administrator\AppData\Local\Temp\ipykernel_16608\4198727415.py:44: PydanticDeprecatedSince20: The
dict
method is deprecated; usemodel_dump
instead. Deprecated in Pydantic V2.0 to be removed in V3.0. See Pydantic V2 Migration Guide at https://errors.pydantic.dev/2.10/migration/
ret.dict(),
流式输出
prompt = PromptTemplate.from_template("讲个关于{topic}的笑话")runnable = ({"topic": RunnablePassthrough()} | prompt | llm | StrOutputParser()
)# 流式输出
for s in runnable.stream("小明"):print(s, end="", flush=True)
好的,那我就给你讲个关于小明的笑话吧!
一天,老师问小明:“如果地球是方的,那会怎么样?”
小明思考了一会儿,非常认真地回答:“那我小时候玩捉迷藏就不用被人发现了,因为我可以直接躲在地球的拐角处!”
老师差点笑到掉书!
注意: 在当前的文档中 LCEL 产生的对象,被叫做 runnable 或 chain,经常两种叫法混用。本质就是一个自定义调用流程。
使用 LCEL 的价值,也就是 LangChain 的核心价值。
官方从不同角度给出了举例说明:https://python.langchain.com/v0.1/docs/expression_language/why/
4.2 用 LCEL 实现 RAG
from langchain_openai import OpenAIEmbeddings
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import FAISS
from langchain_openai import ChatOpenAI
from langchain.chains import RetrievalQA
from langchain_community.document_loaders import PyMuPDFLoader# 加载文档
loader = PyMuPDFLoader("llama2.pdf")
pages = loader.load_and_split()# 文档切分
text_splitter = RecursiveCharacterTextSplitter(chunk_size=300,chunk_overlap=100,length_function=len,add_start_index=True,
)texts = text_splitter.create_documents([page.page_content for page in pages[:4]]
)# 灌库
embeddings = OpenAIEmbeddings(model="text-embedding-ada-002")
db = FAISS.from_documents(texts, embeddings)# 检索 top-2 结果
retriever = db.as_retriever(search_kwargs={"k": 2})
from langchain.schema.output_parser import StrOutputParser
from langchain.schema.runnable import RunnablePassthrough# Prompt模板
template = """Answer the question based only on the following context:
{context}Question: {question}
"""
prompt = ChatPromptTemplate.from_template(template)# Chain
rag_chain = ({"question": RunnablePassthrough(), "context": retriever}| prompt| llm| StrOutputParser()
)rag_chain.invoke("Llama 2有多少参数")
‘根据提供的上下文,Llama 2 有 7B(70亿)、13B(130亿)和 70B(700亿)参数的不同版本。’
4.3 用 LCEL 实现工厂模式
from langchain_core.runnables.utils import ConfigurableField
from langchain_openai import ChatOpenAI
from langchain_community.chat_models import QianfanChatEndpoint
from langchain.prompts import (ChatPromptTemplate,HumanMessagePromptTemplate,
)
from langchain.schema import HumanMessage
import os# 模型1
ernie_model = QianfanChatEndpoint(qianfan_ak=os.getenv('ERNIE_CLIENT_ID'),qianfan_sk=os.getenv('ERNIE_CLIENT_SECRET')
)# 模型2
gpt_model = ChatOpenAI(model="gpt-4o-mini", temperature=0)# 通过 configurable_alternatives 按指定字段选择模型
model = gpt_model.configurable_alternatives(ConfigurableField(id="llm"), default_key="gpt", ernie=ernie_model,# claude=claude_model,
)# Prompt 模板
prompt = ChatPromptTemplate.from_messages([HumanMessagePromptTemplate.from_template("{query}"),]
)# LCEL
chain = ({"query": RunnablePassthrough()} | prompt| model | StrOutputParser()
)# 运行时指定模型 "gpt" or "ernie"
ret = chain.with_config(configurable={"llm": "gpt"}).invoke("请自我介绍")print(ret)
扩展阅读:什么是工厂模式;设计模式概览。
思考:从模块间解依赖角度,LCEL的意义是什么?
4.4 存储与管理对话历史
from langchain_community.chat_message_histories import SQLChatMessageHistorydef get_session_history(session_id):# 通过 session_id 区分对话历史,并存储在 sqlite 数据库中return SQLChatMessageHistory(session_id, "sqlite:///memory.db")
from langchain_core.messages import HumanMessage
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain_openai import ChatOpenAI
from langchain.schema.output_parser import StrOutputParsermodel = ChatOpenAI(model="gpt-4o-mini", temperature=0)runnable = model | StrOutputParser()runnable_with_history = RunnableWithMessageHistory(runnable, # 指定 runnableget_session_history, # 指定自定义的历史管理方法
)runnable_with_history.invoke([HumanMessage(content="你好,我叫大拿")],config={"configurable": {"session_id": "dana"}},
)
d:\envs\langchain-learn\lib\site-packages\langchain_core\runnables\history.py:608: LangChainDeprecationWarning:
connection_string
was deprecated in LangChain 0.2.2 and will be removed in 1.0. Use connection instead.
message_history = self.get_session_history(
‘你好,大拿!很高兴再次见到你。有任何问题或想聊的话题吗?’
runnable_with_history.invoke([HumanMessage(content="你知道我叫什么名字")],config={"configurable": {"session_id": "dana"}},
)
‘是的,你叫大拿。有什么我可以为你做的呢?’
runnable_with_history.invoke([HumanMessage(content="你知道我叫什么名字")],config={"configurable": {"session_id": "test"}},
)
‘抱歉,我不知您的名字。如果您愿意,可以告诉我您的名字。’
通过 LCEL,还可以实现
- 配置运行时变量:https://python.langchain.com/v0.3/docs/how_to/configure/
- 故障回退:https://python.langchain.com/v0.3/docs/how_to/fallbacks
- 并行调用:https://python.langchain.com/v0.3/docs/how_to/parallel/
- 逻辑分支:https://python.langchain.com/v0.3/docs/how_to/routing/
- 动态创建 Chain: https://python.langchain.com/v0.3/docs/how_to/dynamic_chain/
更多例子:https://python.langchain.com/v0.3/docs/how_to/lcel_cheatsheet/
五、LangServe
LangServe 用于将 Chain 或者 Runnable 部署成一个 REST API 服务。
# 安装 LangServe
# pip install --upgrade "langserve[all]"# 也可以只安装一端
# pip install "langserve[client]"
# pip install "langserve[server]"
5.1、Server 端
#!/usr/bin/env python
from fastapi import FastAPI
from langchain.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langserve import add_routes
import uvicornapp = FastAPI(title="LangChain Server",version="1.0",description="A simple api server using Langchain's Runnable interfaces",
)model = ChatOpenAI(model="gpt-4o-mini")
prompt = ChatPromptTemplate.from_template("讲一个关于{topic}的笑话")
add_routes(app,prompt | model,path="/joke",
)if __name__ == "__main__":uvicorn.run(app, host="localhost", port=9999)
5.2、Client 端
import requestsresponse = requests.post("http://localhost:9999/joke/invoke",json={'input': {'topic': '小明'}}
)
print(response.json())
LangChain 与 LlamaIndex 的错位竞争
LangChain 侧重与 LLM 本身交互的封装Prompt、LLM、Message、OutputParser 等工具丰富在数据处理和 RAG 方面提供的工具相对粗糙主打 LCEL 流程封装配套 Agent、LangGraph 等智能体与工作流工具另有 LangServe 部署工具和 LangSmith 监控调试工具
LlamaIndex 侧重与数据交互的封装数据加载、切割、索引、检索、排序等相关工具丰富Prompt、LLM 等底层封装相对单薄配套实现 RAG 相关工具有 Agent 相关工具,不突出
LlamaIndex 为 LangChain 提供了集成在 LlamaIndex 中调用 LangChain 封装的 LLM 接口:https://docs.llamaindex.ai/en/stable/api_reference/llms/langchain/将 LlamaIndex 的 Query Engine 作为 LangChain Agent 的工具:https://docs.llamaindex.ai/en/v0.10.17/community/integrations/using_with_langchain.htmlLangChain 也 曾经 集成过 LlamaIndex,目前相关接口仍在:https://api.python.langchain.com/en/latest/retrievers/langchain_community.retrievers.llama_index.LlamaIndexRetriever.html
总结
LangChain 随着版本迭代可用性有明显提升
使用 LangChain 要注意维护自己的 Prompt,尽量 Prompt 与代码逻辑解依赖
它的内置基础工具,建议充分测试效果后再决定是否使用
相关文章:
面向大模型的开发框架LangChain
这篇文章会带给你 如何使用 LangChain:一套在大模型能力上封装的工具框架如何用几行代码实现一个复杂的 AI 应用面向大模型的流程开发的过程抽象 文章目录 这篇文章会带给你写在前面LangChain 的核心组件文档(以 Python 版为例)模型 I/O 封装…...
每日算法:洛谷U535992 J-C 小梦的宝石收集(双指针、二分)
题目描述 小梦有 n 颗能量宝石,其中第 i 颗的能量为 ai,但这些能量宝石十分不稳定,随时有可能发生崩坏,导致他们全部消失! 小梦想要留住宝石们,不希望他们发生崩坏,同时他发现:如…...
写给新人的深度学习扫盲贴:ReLu和梯度
一、ReLU(Rectified Linear Unit,修正线性单元) 梯度是深度学习中最常用的激活函数之一,因其简单、高效且能有效缓解梯度消失问题而被广泛使用。 1. 数学定义 函数表达式: $$ \text{ReLU}(x) \max(0, x) \begin{…...
Spring 框架的核心基础:IoC 和 AOP
一、IoC(Inversion of Control,控制反转) 定义: IoC(Inversion of Control,控制反转),就是把对象创建和依赖关系的管理交给 Spring 容器,而不是由程序员手动去创建对象…...
JavaScript逆向工程实战:如何精准定位加密参数生成位置
前言:一个令人困惑的调试案例 最近在进行某网站的JavaScript逆向分析时,我遇到了一个有趣的现象:当我尝试定位一个名为m的加密参数(值为MTIwMTE3NDQxODk1NTY1NjkA这样的Base64字符串)时,调试器却带我来到了…...
SSM智能停车场管理系统
🍅点赞收藏关注 → 添加文档最下方联系方式咨询本源代码、数据库🍅 本人在Java毕业设计领域有多年的经验,陆续会更新更多优质的Java实战项目希望你能有所收获,少走一些弯路。🍅关注我不迷路🍅 项目视频 SS…...
[定位器]晶艺LA1823,4.5V~100V, 3.5A,替换MP9487,MP9486A,启烨科技
Features 4.5V to 100V Wide Input Range 3.5A Typical Peak Current Limit Integrated 500mΩ low resistance high side power MOS. Constant On Time Control with Constant Switching Frequency. 180μA Low Quiescent Current 150kHz/240kHz/420kHz Swi…...
天元证券|A股大反攻!北证50涨超10%!芯片股大爆发
今日,A股全线走强。 科技成长股领涨,北证50指数飙升逾10%,科创50也大涨超4%,深证成指、上证指数午后也稳步拉升涨逾1%。值得注意的是,上证50指数临近收盘集合竞价的时候直线拉升。近4600只个股上涨,成交稳步…...
利用python从零实现Byte Pair Encoding(BPE):NLP 中的“变形金刚”
BPE:NLP 界的“变形金刚”,从零开始的奇幻之旅 在自然语言处理(NLP)的世界里,有一个古老而神秘的传说,讲述着一种强大的魔法——Byte Pair Encoding(BPE)。它能够将普通的文本“变形…...
最新Web系统全面测试指南
你有没有遇到过这样的情况: 系统上线当天,用户频频报错,运维一脸懵逼,开发说“我本地没问题”? 你明明写了几十个测试用例,结果却还是有 Bug 漏网? Web 系统测试,不只是点点点&#…...
OpenBMC:BmcWeb 处理http请求6 调用路由处理函数
OpenBMC:BmcWeb 处理http请求5 检查权限-CSDN博客 检查完权限后,调用了rule.handle(*req, asyncResp, params); template <typename... Args> class TaggedRule :public BaseRule,public RuleParameterTraits<TaggedRule<Args...>> {void handle(const Req…...
售货机管理系统:智慧零售时代的运营新引擎
一、引言 在快节奏的都市生活中,自动售货机已成为便捷消费的重要场景。然而,传统售货机依赖人工补货、手工对账,常面临库存失衡、设备故障发现滞后、数据孤岛等痛点。如何突破效率瓶颈?本文将深入剖析榕壹云售货机管理系统的项目背景、客户定位、技术与核心功能、系统优势…...
Python基础全解析:从输入输出到字符编码的深度探索
一、Python程序交互的基石:Print函数详解 1.1 基础输出功能 # 输出数字 print(20.5) # 输出浮点数:20.5 print(0b0010) # 输出二进制数:10# 输出字符串 print(Hello World!) # 经典输出示例# 表达式计算 print(4 4 * (2-1)…...
Python第八章02:数据可视化Pyecharts包无法使用
PS:本节纯属个人在学习过程中遇到问题、解决问题的经验分享,对学习进度没影响,没有遇到该问题的小伙伴可跳过。 首先,在学习数据图形化过程中,通过命令提示符安装了Pyecharts包,在命令提示符中验证安装成功。 在PyChar…...
【人工智能】如何通过精准提示工程实现完美的珠宝首饰展示
AI艺术创作指南:如何通过精准提示工程实现完美的珠宝首饰展示 引言:认知边界的突破 在AI艺术创作的漫长探索中,许多创作者面临着相似的困扰:当他们看到别人能够通过算法编织出如同文艺复兴时期细腻油画般的奢华珠宝展示图&#…...
Redis学习总结(持续更新)
Redis 目前在学习redis,遇到的一些问题会放在这里,加深自己的印象。 1. Redis缓存相较于传统Session存储的特点 Session的存储方式: 通常,传统的Session是存储在应用服务器的内存中,比如Tomcat的Session管理器。用户…...
RabbitMQ从入门到实战-3(高可靠性)
文章目录 发送者可靠性发送者重连发送者确认(一般不会开启)指定returncallback和confrimfallbacktips MQ可靠性数据持久化LazyQueue(默认模式且不可更改) 消费者的可靠性消费者确认机制消费者失败重试业务幂等性唯一消息id业务判断…...
RTK 实时动态定位概述
01 引言 RTK(实时动态定位,Real-Time Kinematic)是一种高精度的卫星导航定位技术,通过差分校正方法,将GNSS(全球导航卫星系统)的定位精度从米级提升至厘米级(通常1-3厘米),广泛应用于测绘、无人机、自动驾驶、精准农业等领域。 02 概述 1. RTK的基本原理 RTK的核…...
Conda 环境离线迁移实战:解决生产环境网络限制的高效方案20250409
Conda 环境离线迁移实战:解决生产环境网络限制的高效方案 在生产环境无法联网的前提下,如何高效、安全地部署 Python 虚拟环境,是许多企业在实际运维中必须面对的问题。特别是当前常见的开发环境基于 Miniconda,生产环境使用 Ana…...
dify使用知识库
注意 要用向量模型 导入文件 选择向量模型 要下载好后,才可以导入模型, 这个模型没法在ollama中run 聊天工具添加知识库 效果...
HTTP:一.概述
http是干嘛的? 超文本传输协议(英语:HyperText Transfer Protocol,缩写:HTTP)是一种用于分布式、协作式和超媒体信息系统的应用层协议。HTTP是万维网的数据通信的基础。设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法。通过HTTP或者HTTPS协议请求的资源由统…...
Appium工作原理及环境的搭建(1)
1、Appium的介绍: 一、什么是Appium Desktop? Appium Desktop是Appium项目的桌面版GUI工具,提供了一个友好的界面,用于启动Appium服务器、查看设备日志、与设备交互、调试自动化脚本等。相比于命令行工具,Appium Des…...
Interactron: Embodied Adaptive Object Detection(训练时进行更新参数) 还没看懂
Interactron: Embodied Adaptive Object Detection 创新点 这些方法通常存在两个主要的共同假设。第一,模型在固定的训练集上进行训练,并在预先录制的测试集上进行评估。第二,模型在训练阶段结束后保持冻结状态,即训练完成后不再…...
【Pandas】pandas DataFrame copy
Pandas2.2 DataFrame Conversion 方法描述DataFrame.astype(dtype[, copy, errors])用于将 DataFrame 中的数据转换为指定的数据类型DataFrame.convert_dtypes([infer_objects, …])用于将 DataFrame 中的数据类型转换为更合适的类型DataFrame.infer_objects([copy])用于尝试…...
Redis基础指令(Windows)
1.cmd命令行启动redis 直接cmd打开整个文件 1.1.启动server 输入指令: redis-server.exe redis.windows.conf 会进入serve端 1.2.启动客户端 !!重新打开一个cmd,方法和上面一样!! 之后输入 redis-…...
MV-DLS600P激光振镜立体相机(MV-DLS600P)重要参数解析
功能特性 采用激光振镜技术,亚毫米级图像采集精度 高能效激光模块配合精准曝光同步,性能更稳定 支持多帧融合,无惧金属工件表面反光干扰 支持RGB、深度图同步对齐输出,便于二次开发 配备窄带滤光片,抗干扰能力更强&…...
C语言【输出字符串中的大写字母】
题目 输出字符串中的大写字母 思路(注意事项) 纯代码 #include<stdio.h> #include<string.h>int main(){char str[20], ans[20];fgets(str, sizeof(str), stdin);str[strcspn(str, "\n")] \0;for (int i 0, j 0; i < strl…...
UniApp基于xe-upload实现文件上传组件
xe-upload地址:文件选择、文件上传组件(图片,视频,文件等) - DCloud 插件市场 致敬开发者!!! 感觉好用的话,给xe-upload的作者一个好评 背景:开发中经常会有…...
deque容器
1.定义 也叫双端数组,可以对头部进行插入和删除。 2.与vector区别 3.内部工作原理 他是把整个地址划分成多块小地址(缓冲区),然后有一个中控区去记录这些地址,然后访问的时候先通过中控区然后再转到相应的缓冲区&am…...
git 总结遇到的问题
git Push 报错 Push failed send-pack: unexpected disconnect while reading sideband packet Total 2269 (delta 418), reused 0 (delta 0), pack-reused 0 the remote end hung up unexpectedly 解决方案:增加 Git 的缓冲区,有时由于数据量大或网络…...
python基础语法11-文件读写
在 Python 中,文件操作是日常编程中的常见任务之一。Python 提供了简单且强大的工具来读取和写入文件。通过使用内置的 open() 函数、read()、readline()、write() 等方法,我们可以轻松实现对文件的操作。此外,Python 的 with 语句可以帮助我…...
Webstorm 使用搜不到node_modules下的JS内容 TS项目按Ctrl无法跳转到函数实现
将node_modules标记为不排除,此时要把内存改大,不然webstorm中途建立索引时,会因为内存不足,导致索引中途停止,造成后续搜索不出来 更改使用内存设置 内存调为4096 若出现搜不出来js内容时,请直接重启下该项…...
转行嵌入式,需要自学多久?
作为一个本硕都学机械,却阴差阳错进入嵌入式行业的老兵,这个问题我能聊一整天。十几年前我还在工厂车间穿着工装和机床打交道,偶然接触到单片机后就一发不可收拾。 转行这条路我走得异常艰辛,踩过的坑比写过的代码还多。去年我终…...
BLE 协议栈事件驱动机制详解
在 BlueNRG-LP 等 BLE 系统中,事件驱动是控制状态转移、数据交互和外设协作的基础。本文将深入讲解 BLE 协议栈中事件的来源、分发流程、处理结构与实际工程实践策略,帮助你构建稳定、可维护的 BLE 系统。 📦 一、BLE 事件的来源分类 BLE 协议栈中的事件严格来自协议栈本身…...
AI开发学习路线(闯关升级版)
以下是一份轻松版AI开发学习路线,用「闯关升级」的方式帮你从零开始变身AI开发者,每个阶段都配有有趣的任务和实用资源,保证不枯燥、可落地!👇 目录 🔰 新手村:打基础(1-2个月&…...
突破,未观测地区罕见极端降雨的估计
文章中文总结(重点为方法细节) 一、研究背景与目的 在无测站或短观测记录地区,传统极值理论(如GEV)难以估计稀有极端降雨事件;本文提出一种新的区域化极值估计方法:区域化 Metastatistical Ex…...
zk源码—4.会话的实现原理一
大纲 1.创建会话 (1)客户端的会话状态 (2)服务端的会话创建 (3)会话ID的初始化实现 (4)设置的会话超时时间没生效的原因 2.分桶策略和会话管理 (1)分桶策略和过期队列 (2)会话激活 (3)会话超时检查 (4)会话清理 1.创建会话 (1)客户端的会话状态 (2)服务端的会话创建…...
快排算法 (分治实现)
本算法采用将整个数组划分成三个部分 <key key >key 在数组全是同一个数字时,也能达到NlogN的时间复杂度 下面的板书中i为遍历数组的下标 left为<key的最右边的下标 right为>key的最左边的下标 例题1:912. 排序数组 - 力扣࿰…...
P9242 [蓝桥杯 2023 省 B] 接龙数列
这道题说要求最少删多少个使剩下的序列是接龙序列,这个问题可以转换为序列中最长的接龙序列是多少,然后用总长度减去最长接龙序列的长度就可以了,在第一个暴力版本的代码中我用了两个for循环求出了所有的接龙序列的长度,但是会超时…...
未来 AI 发展趋势与挑战(AGI、数据安全、监管政策)
从 ChatGPT 的火爆到国内 DeepSeek、通义千问、百川智能等模型的兴起,AI 正以前所未有的速度走入各行各业。而下一阶段,AI 是否会发展出真正的“通用智能”(AGI)?数据隐私、技术伦理又该如何应对?本文将带你全面洞察未来 AI 的技术趋势与落地挑战。 一、AGI 的曙光:通用…...
驱动开发硬核特训 · Day 6 : 深入解析设备模型的数据流与匹配机制 —— 以 i.MX8M 与树莓派为例的实战对比
🔍 B站相应的视屏教程: 📌 内核:博文视频 - 从静态绑定驱动模型到现代设备模型 主题:深入解析设备模型的数据流与匹配机制 —— 以 i.MX8M 与树莓派为例的实战对比 在上一节中,我们从驱动框架的历史演进出…...
MyBatis 动态 SQL 使用详解
🌟 一、什么是动态 SQL? 动态 SQL 是指根据传入参数,动态拼接生成 SQL 语句,不需要写多个 SQL 方法。MyBatis 提供了 <if>、<choose>、<foreach>、<where> 等标签来实现这类操作 ✅ 二、动态 SQL 的优点…...
数据结构实验4.1:链队列的基本操作
文章目录 一,问题描述二,基本要求三,算法分析链队列的存储结构设计基本操作的算法分析 四,示例代码五,实验操作六,运行效果 一,问题描述 编程实现有关链队列的下列基本操作。 (1&am…...
独立部署及使用Ceph RBD块存储
Ceph RBD(RADOS Block Device) 是 Ceph 分布式存储系统中的块存储组件,类似于 AWS EBS、iSCSI 等。它独立于 OpenShift 或 IBM CP4BA,是一个分布式存储系统,提供高性能、可扩展性和容错能力,适用于数据库、…...
C++初阶-C++入门基础
目录 编辑 1.C的简介 1.1C的产生和发展 1.2C的参考文档 1.3C优势和难度 1.4C学习的建议 2.C的第一个程序 2.1打印Hello world 2.2头文件 2.3namespace命名空间 2.4::作用域限定符 2.5namespace的延伸 2.6C的输入输出 3.总结 1.C的简介 …...
部署大模型不再难:DeepSeek + 腾讯云 HAI 实战教程
网罗开发 (小红书、快手、视频号同名) 大家好,我是 展菲,目前在上市企业从事人工智能项目研发管理工作,平时热衷于分享各种编程领域的软硬技能知识以及前沿技术,包括iOS、前端、Harmony OS、Java、Python等…...
算法训练之位运算
♥♥♥~~~~~~欢迎光临知星小度博客空间~~~~~~♥♥♥ ♥♥♥零星地变得优秀~也能拼凑出星河~♥♥♥ ♥♥♥我们一起努力成为更好的自己~♥♥♥ ♥♥♥如果这一篇博客对你有帮助~别忘了点赞分享哦~♥♥♥ ♥♥♥如果有什么问题可以评论区留言或者私信我哦~♥♥♥ ✨✨✨✨✨✨ 个…...
初识Linux:常见指令与权限的理解,以及相关衍生知识
目录 前言 关于linux的简介 代码开源 网络功能强大 系统工具链完整 一、Linux下的基本指令 1.ls指令 2.pwd指令 3.cd指令 4.whoami指令 5.touch指令 6.mkdir指令 7.rm指令 8.man指令 9.cp指令 10.mv指令 11.nano指令 12.cat指令 13.tac指令 14.more指令 15.less指令 16.head指令…...
PostgreSQL-数据库的索引 pg_operator_oid_index 损坏
报错信息: 连接测试失败 Error connecting to database: Connection failed: ERROR: index "pg_operator_oid_index" contains unexpected zero page at block 3 Hint: Please REINDEX it. 这个错误表明 PostgreSQL 数据库的索引 pg_operator_oid_index …...
数字图像处理作业4
数字图像处理 作业4 Project 4:Image Restoration The scoring method for this project is as follows: 1.Implement a blurring filter using the equation(5.6-11,数字图像处理(…...