学习笔记(一)——Langchain基本操作与函数

学习笔记(一)——Langchain基本操作与函数

目录

  • 学习笔记(一)——Langchain基本操作与函数
    • 基本初始化配置
      • Langsmith
      • Language Models
    • 基础指令
      • 传递信息
      • OutputParsers 输出解析器
      • chain 链
      • Prompt Templates 提示模板
      • Message History 消息历史记录
      • Managing Conversation History 管理对话历史记录
      • Streaming 流
    • Vector stores and retrievers 矢量存储和检索器
      • 文档document
      • Vector stores 矢量存储
      • Retrievers
    • Agent/使用工具
    • 服务器
      • 构建服务器
      • 访问服务器

基本初始化配置

Langsmith

这个主要可以观察数据请求和结果的,官网:langsmith

设置环境变量

export LANGCHAIN_TRACING_V2="true"
export LANGCHAIN_API_KEY="..."

如果是windows,可以打开这个进行设置
在这里插入图片描述

或者使用这个(PS:我觉得不好用,每次运行都需要输入账号密码,如果是jupyter可以尝试,建议上面的方法)

import getpass
import osos.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_API_KEY"] = getpass.getpass()

Language Models

通常使用chatgpt,但是国内使用chatgpt直连极易被封(即使你是gpt4会员,也会秒封,亲身经历)。建议使用API和跳转:

在用的API跳转:API

import osos.environ["OPENAI_API_KEY"] = "sk_跳转API的密钥"# openai的模型调用
from langchain_openai import ChatOpenAI#基础网址也可能是:https://one-api.bltcy.top,如果还是不行,那个API网址还有几个,尝试即可
model = ChatOpenAI(model="gpt-4",base_url='https://one-api.bltcy.top/v1')

基础指令

传递信息

.invoke目标是将消息列表message传递给模型,当然不一定非要是大语言模型,这个传递消息用的很多。

HumanMessage是我们要提供的信息。

SystemMessage是用于启动 AI 行为的消息,通常作为序列中的第一个传入 的输入消息。

AIMessage 从AI获取的消息,大致上可以理解为,之前的历史记录

from langchain_core.messages import HumanMessage, SystemMessagemessages = [SystemMessage(content="Translate the following from English into Italian"),HumanMessage(content="hi!"),
]print(model.invoke(messages))
# AIMessage(content='ciao!', response_metadata={'token_usage': {'completion_tokens': 3, 'prompt_tokens': 20, 'total_tokens': 23}, 'model_name': 'gpt-4', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-fc5d7c88-9615-48ab-a3c7-425232b562c5-0')
from langchain_core.messages import AIMessagemessage=[HumanMessage(content="Hi! I'm Bob"),AIMessage(content="Hello Bob! How can I assist you today?"),HumanMessage(content="What's my name?"),]
res=model.invoke(message)
print(res)
# AIMessage(content='Your name is Bob.', response_metadata={'token_usage': {'completion_tokens': 5, 'prompt_tokens': 35, 'total_tokens': 40}, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': 'fp_c2295e73ad', 'finish_reason': 'stop', 'logprobs': None}, id='run-5692718a-5d29-4f84-bad1-a9819a6118f1-0')

OutputParsers 输出解析器

之前是给了一堆信息,但是,我们可能只想使用字符串响应。我们可以使用简单的输出解析器来解析此响应。

StrOutputParser()

from langchain_core.output_parsers import StrOutputParserparser = StrOutputParser()result = model.invoke(messages)print(parser.invoke(result))
#'Ciao!'

chain 链

更常见的是,我们可以用这个输出解析器“chian”模型。这意味着此输出解析器将在此链中每次被调用。该链采用语言模型的输入类型(字符串或消息列表),并返回输出解析器的输出类型(字符串)。

chain = model | parser
print(chain.invoke(messages))
#'Ciao!'

Prompt Templates 提示模板

现在,我们将消息列表直接传递到语言模型中。此消息列表从何而来?通常,它是由用户输入和应用程序逻辑的组合构建的。此应用程序逻辑通常采用原始用户输入,并将其转换为准备传递给语言模型的消息列表。常见的转换包括添加系统消息或使用用户输入设置模板的格式。

PromptTemplates 是 LangChain 中的一个概念,旨在帮助实现这种转换。它们接收原始用户输入并返回准备传递到语言模型中的数据(提示)。

简单来说,就是每次我们不想重复输入一大堆文本,我们可以事先写几个prompt告诉模型要干啥。

Prompt Templates

from langchain_core.prompts import ChatPromptTemplate
system_template = "Translate the following into {language}:"
prompt_template = ChatPromptTemplate.from_messages([("system", system_template), ("user", "{text}")]
)
result = prompt_template.invoke({"language": "italian", "text": "hi"})
print(result)
#ChatPromptValue(messages=[SystemMessage(content='Translate the following into italian:'), HumanMessage(content='hi')])

直接访问消息,可以使用to_messages()

print(result.to_messages())
[SystemMessage(content='Translate the following into italian:'),HumanMessage(content='hi')]

还可以继续形成chain,这样就方便很多了

chain = prompt_template | model | parser
res=chain.invoke({"language": "italian", "text": "hi"})
print(res)

Message History 消息历史记录

我们可以使用 Message History 类来包装我们的模型并使其有状态。这将跟踪模型的输入和输出,并将它们存储在某个数据存储中。然后,未来的交互将加载这些消息,并将它们作为输入的一部分传递到链中。

之后,我们可以导入相关类并设置我们的链,该链包装模型并添加此消息历史记录。这里的一个关键部分是我们传入的函数。 get_session_history 此函数应接受并 session_id 返回 Message History 对象。这 session_id 用于区分单独的对话,并且在调用新链时应作为配置的一部分传入。

from langchain_community.chat_message_histories import ChatMessageHistory
from langchain_core.chat_history import BaseChatMessageHistory
from langchain_core.runnables.history import RunnableWithMessageHistorystore = {}def get_session_history(session_id: str) -> BaseChatMessageHistory:if session_id not in store:store[session_id] = ChatMessageHistory()return store[session_id]#大致上就是每次模型如果对话了,保存对话到store
with_message_history = RunnableWithMessageHistory(model, get_session_history)

我们现在需要创建一个每次都传递到可运行对象中 config 。此配置包含的信息不是直接输入的一部分,但仍然有用。在本例中,我们希望包含一个session_id这应该如下所示:

config = {"configurable": {"session_id": "abc2"}}
#实例化执行带有记忆的model,即对话会存储内容
response = with_message_history.invoke([HumanMessage(content="Hi! I'm Bob")],config=config,
)print(response.content)
#'Hello Bob! How can I assist you today?'
response = with_message_history.invoke([HumanMessage(content="What's my name?")],config=config,
)
print(response.content)
# 'Your name is Bob.'

我们的聊天机器人现在记住了关于我们的事情。如果我们更改配置以引用不同的 session_id,我们可以看到它重新开始对话。

config = {"configurable": {"session_id": "abc3"}}response = with_message_history.invoke([HumanMessage(content="What's my name?")],config=config,
)
print(response.content)
# "I'm sorry, I do not have the ability to know your name unless you tell me."

我们还可以利用MessagesPlaceholder 所有消息传递。

MessagesPlaceholder

请注意,这略微改变了输入类型 - 我们现在不是传入消息列表,而是传入一个带有 messages键的字典,其中包含消息列表。

from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholderprompt = ChatPromptTemplate.from_messages([("system","You are a helpful assistant. Answer all questions to the best of your ability.",),MessagesPlaceholder(variable_name="messages"),]
)
chain = prompt | model
with_message_history = RunnableWithMessageHistory(chain, get_session_history)
config = {"configurable": {"session_id": "abc5"}}
response = with_message_history.invoke([HumanMessage(content="Hi! I'm Jim")],config=config,
)
print(response.content)
# 'Hello, Jim! How can I assist you today?'
response = with_message_history.invoke([HumanMessage(content="What's my name?")],config=config,
)
print(response.content)
#'Your name is Jim. How can I assist you further, Jim?'

现在让我们的提示稍微复杂一点。让我们假设提示模板现在看起来像这样:

prompt = ChatPromptTemplate.from_messages([("system","You are a helpful assistant. Answer all questions to the best of your ability in {language}.",),MessagesPlaceholder(variable_name="messages"),]
)
chain = prompt | model
with_message_history = RunnableWithMessageHistory(chain,get_session_history,input_messages_key="messages",
)
config = {"configurable": {"session_id": "abc11"}}
response = with_message_history.invoke({"messages": [HumanMessage(content="hi! I'm todd")], "language": "Spanish"},config=config,
)
print(response.content)
# '¡Hola Bob! ¿En qué puedo ayudarte hoy?'
response = with_message_history.invoke({"messages": [HumanMessage(content="whats my name?")], "language": "Spanish"},config=config,
)
print(response.content)
#'Tu nombre es Todd. ¿Hay algo más en lo que pueda ayudarte?'

Managing Conversation History 管理对话历史记录

构建聊天机器人时要了解的一个重要概念是如何管理对话历史记录。如果不进行管理,消息列表将无限制增长,并可能溢出 LLM.因此,添加一个步骤来限制您传入的消息的大小非常重要。

重要的是,您需要在提示模板之前执行此操作,但在从消息历史记录加载以前的消息之后执行此操作。

为此,我们可以在提示符前面添加一个简单的步骤来适当地修改 messages 密钥,然后将该新链包装在 Message History 类中。首先,让我们定义一个函数来修改传入的消息。让我们让它选择 k 最新的消息。然后,我们可以通过在开始时添加它来创建一个新链。

如果我们创建一个超过 10 条消息的消息列表,我们可以看到它不再记住早期消息中的信息。

from langchain_core.runnables import RunnablePassthroughdef filter_messages(messages, k=10):return messages[-k:]chain = (RunnablePassthrough.assign(messages=lambda x: filter_messages(x["messages"]))| prompt| model
)
messages = [HumanMessage(content="hi! I'm bob"),AIMessage(content="hi!"),HumanMessage(content="I like vanilla ice cream"),AIMessage(content="nice"),HumanMessage(content="whats 2 + 2"),AIMessage(content="4"),HumanMessage(content="thanks"),AIMessage(content="no problem!"),HumanMessage(content="having fun?"),AIMessage(content="yes!"),
]with_message_history = RunnableWithMessageHistory(chain,get_session_history,input_messages_key="messages",
)
config = {"configurable": {"session_id": "abc20"}}
response = with_message_history.invoke({"messages": messages + [HumanMessage(content="whats my name?")],"language": "English",},config=config,
)print(response.content)
#"I'm sorry, I don’t have access to your name. Can I help you with anything else?"

Streaming 流

LLMs有时可能需要一段时间才能做出响应,因此为了改善用户体验,大多数应用程序所做的一件事就是在生成每个令牌时流回每个令牌。

所有链都公开一个 .stream方法,使用消息历史记录的链也不例外。我们可以简单地使用该方法来返回流式响应。

config = {"configurable": {"session_id": "abc15"}}
for r in with_message_history.stream({"messages": [HumanMessage(content="hi! I'm todd. tell me a joke")],"language": "English",},config=config,
):print(r.content, end="|")

Vector stores and retrievers 矢量存储和检索器

文档document

LangChain实现了一个文档抽象,旨在表示文本单元和关联的元数据。它有两个属性:

  • page_content :表示内容的字符串;
  • metadata :包含任意元数据的字典。

metadata属性可以捕获有关文档源、文档与其他文档的关系以及其他信息的信息。请注意,单个 Document 对象通常表示较大文档的块。

from langchain_core.documents import Documentdocuments = [Document(page_content="Dogs are great companions, known for their loyalty and friendliness.",metadata={"source": "mammal-pets-doc"},),Document(page_content="Cats are independent pets that often enjoy their own space.",metadata={"source": "mammal-pets-doc"},),Document(page_content="Goldfish are popular pets for beginners, requiring relatively simple care.",metadata={"source": "fish-pets-doc"},),Document(page_content="Parrots are intelligent birds capable of mimicking human speech.",metadata={"source": "bird-pets-doc"},),Document(page_content="Rabbits are social animals that need plenty of space to hop around.",metadata={"source": "mammal-pets-doc"},),
]

Vector stores 矢量存储

from langchain_chroma import Chroma
from langchain_openai import OpenAIEmbeddingsvectorstore = Chroma.from_documents(documents,embedding=OpenAIEmbeddings(base_url='https://one-api.bltcy.top/v1'),
)
#根据与嵌入查询的相似性返回文档:
embedding = OpenAIEmbeddings(base_url='https://one-api.bltcy.top/v1').embed_query("cat")
# [Document(page_content='Cats are independent pets that often enjoy their own space.', metadata={'source': 'mammal-pets-doc'}),
# Document(page_content='Dogs are great companions, known for their loyalty and friendliness.', metadata={'source': 'mammal-pets-doc'}),
# Document(page_content='Rabbits are social animals that need plenty of space to hop around.', metadata={'source': 'mammal-pets-doc'}),
# Document(page_content='Parrots are intelligent birds capable of mimicking human speech.', metadata={'source': 'bird-pets-doc'})]

Retrievers

LangChain VectorStore 对象不对 Runnable 进行子类化,因此无法立即集成到 LangChain 表达式语言链中。

LangChain检索器是可运行的,因此它们实现了一组标准方法(例如,同步和异步 invoke 以及 batch 操作),并被设计为合并到LCEL链中。

我们可以自己创建一个简单的版本,而无需子 Retriever 类化。如果我们选择我们希望使用哪种方法来检索文档,我们可以轻松创建一个可运行的。下面我们将围绕 similarity_search 该方法构建一个:

from typing import Listfrom langchain_core.documents import Document
from langchain_core.runnables import RunnableLambdaretriever = RunnableLambda(vectorstore.similarity_search).bind(k=1)  # select top result
print(retriever.batch(["cat", "shark"]))
# [[Document(page_content='Cats are independent pets that often enjoy their own space.', metadata={'source': 'mammal-pets-doc'})],
# [Document(page_content='Goldfish are popular pets for beginners, requiring relatively simple care.', metadata={'source': 'fish-pets-doc'})]]

系统实例:

import getpass
import os
from langchain_core.documents import Document
from langchain_openai import ChatOpenAI
from typing import List
from langchain_chroma import Chroma
from langchain_openai import OpenAIEmbeddings
from langchain_core.documents import Document
from langchain_core.runnables import RunnableLambda
import getpass
import os
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthroughos.environ['OPENAI_API_KEY'] = 'sk-'documents = [Document(page_content="Dogs are great companions, known for their loyalty and friendliness.",metadata={"source": "mammal-pets-doc"},),Document(page_content="Cats are independent pets that often enjoy their own space.",metadata={"source": "mammal-pets-doc"},),Document(page_content="Goldfish are popular pets for beginners, requiring relatively simple care.",metadata={"source": "fish-pets-doc"},),Document(page_content="Parrots are intelligent birds capable of mimicking human speech.",metadata={"source": "bird-pets-doc"},),Document(page_content="Rabbits are social animals that need plenty of space to hop around.",metadata={"source": "mammal-pets-doc"},),
]vectorstore = Chroma.from_documents(documents,embedding=OpenAIEmbeddings(base_url='https://one-api.bltcy.top/v1'),
)retriever = vectorstore.as_retriever(search_type="similarity",search_kwargs={"k": 1},
)# os.environ["OPENAI_API_KEY"] = getpass.getpass()llm = ChatOpenAI(model="gpt-3.5-turbo-0125",base_url='https://one-api.bltcy.top/v1')message = """
Answer this question using the provided context only.{question}Context:
{context}
"""prompt = ChatPromptTemplate.from_messages([("human", message)])rag_chain = {"context": retriever, "question": RunnablePassthrough()} | prompt | llm
response = rag_chain.invoke("tell me about cats")print(response.content)

Agent/使用工具

我们将使用 Tavily(搜索引擎)作为工具。为了使用它,您需要获取并设置一个 API 密钥:tavily

我们首先需要创建我们想要使用的工具。我们选择的主要工具将是 Tavily - 一个搜索引擎。我们在LangChain中有一个内置工具,可以轻松地使用Tavily搜索引擎作为工具。

from langchain_community.tools.tavily_search import TavilySearchResultssearch = TavilySearchResults(max_results=2)
search_results = search.invoke("what is the weather in SF")
print(search_results)
#如果我们愿意,我们可以创建其他工具。
#一旦我们有了我们想要的所有工具,我们可以把它们放在一个列表中,我们以后会引用它们。
tools = [search]
print(tools)

使用工具可以:

model_with_tools = model.bind_tools(tools)response = model_with_tools.invoke([HumanMessage(content="What's the weather in SF?")])print(f"ContentString: {response.content}")
print(f"ToolCalls: {response.tool_calls}")
#ContentString: [{'id': 'toolu_01TSdZjtqppPVYyvrYvsok6d', 'input': {'query': 'san francisco weather'}, 'name': 'tavily_search_results_json', 'type': 'tool_use'}]
#ToolCalls: [{'name': 'tavily_search_results_json', 'args': {'query': 'san francisco weather'}, 'id': 'toolu_01TSdZjtqppPVYyvrYvsok6d'}]

现在我们已经定义了工具和 LLM,我们可以创建代理了。我们将使用 LangGraph 来构建代理。目前,我们正在使用一个高级接口来构建代理,但 LangGraph 的好处是,这个高级接口由一个低级、高度可控的 API 支持,以防你想修改代理逻辑。

from langgraph.prebuilt import create_react_agentagent_executor = create_react_agent(model, tools)response = agent_executor.invoke({"messages": [HumanMessage(content="whats the weather in sf?")]}
)
response["messages"]

如前所述,此代理是无状态的。这意味着它不记得以前的交互。为了给它内存,我们需要传入一个检查点。传入检查点时,我们还必须在调用代理时传入一个 thread_id (以便它知道要从哪个线程/对话恢复)。

from langgraph.checkpoint.sqlite import SqliteSavermemory = SqliteSaver.from_conn_string(":memory:")agent_executor = create_react_agent(model, tools, checkpointer=memory)config = {"configurable": {"thread_id": "abc123"}}
for chunk in agent_executor.stream({"messages": [HumanMessage(content="hi im bob!")]}, config
):print(chunk)print("----")
# {'agent': {'messages': [AIMessage(content="Hello Bob! It's nice to meet you again.", response_metadata={'id': 'msg_013C1z2ZySagEFwmU1EsysR2', 'model': 'claude-3-sonnet-20240229', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'input_tokens': 1162, 'output_tokens': 14}}, id='run-f878acfd-d195-44e8-9166-e2796317e3f8-0', usage_metadata={'input_tokens': 1162, 'output_tokens': 14, 'total_tokens': 1176})]}}
----
for chunk in agent_executor.stream({"messages": [HumanMessage(content="whats my name?")]}, config
):print(chunk)print("----")# {'agent': {'messages': [AIMessage(content='You mentioned your name is Bob when you introduced yourself earlier. So your name is Bob.', response_metadata={'id': 'msg_01WNwnRNGwGDRw6vRdivt6i1', 'model': 'claude-3-sonnet-20240229', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'input_tokens': 1184, 'output_tokens': 21}}, id='run-f5c0b957-8878-405a-9d4b-a7cd38efe81f-0', usage_metadata={'input_tokens': 1184, 'output_tokens': 21, 'total_tokens': 1205})]}}
----

完整示例

# Import relevant functionality
from langchain_anthropic import ChatAnthropic
from langchain_openai import ChatOpenAI
from langchain_community.tools.tavily_search import TavilySearchResults
from langchain_core.messages import HumanMessage
from langgraph.checkpoint.sqlite import SqliteSaver
from langgraph.prebuilt import create_react_agent
import osos.environ['TAVILY_API_KEY'] = 'tvly-'
os.environ['OPENAI_API_KEY'] = 'sk-'memory = SqliteSaver.from_conn_string(":memory:")
model = ChatOpenAI(base_url='https://one-api.bltcy.top/v1')
search = TavilySearchResults(max_results=2)
tools = [search]
agent_executor = create_react_agent(model, tools, checkpointer=memory)# Use the agent
config = {"configurable": {"thread_id": "abc123"}}
for chunk in agent_executor.stream({"messages": [HumanMessage(content="hi im bob! and i live in sf")]}, config
):print(chunk)print("----")for chunk in agent_executor.stream({"messages": [HumanMessage(content="whats the weather where I live?")]}, config
):print(chunk)print("----")

服务器

构建服务器

为了为我们的应用程序创建一个服务器,我们将创建一个 serve.py 文件。这将包含我们为应用程序提供服务的逻辑。它由三件事组成:

  1. 我们刚刚在上面构建的链的定义
  2. 我们的 FastAPI 应用程序
  3. 为链提供服务的路由的定义,这是通过 langserve.add_routes

PS:官网案例,记得修改api

#!/usr/bin/env python
from typing import Listfrom fastapi import FastAPI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_openai import ChatOpenAI
from langserve import add_routes# 1. Create prompt template
system_template = "Translate the following into {language}:"
prompt_template = ChatPromptTemplate.from_messages([('system', system_template),('user', '{text}')
])# 2. Create model
model = ChatOpenAI()# 3. Create parser
parser = StrOutputParser()# 4. Create chain
chain = prompt_template | model | parser# 4. App definition
app = FastAPI(title="LangChain Server",version="1.0",description="A simple API server using LangChain's Runnable interfaces",
)# 5. Adding chain routeadd_routes(app,chain,path="/chain",
)if __name__ == "__main__":import uvicornuvicorn.run(app, host="localhost", port=8000)

核心就这个部分:

# 创建服务器API设置
app = FastAPI(title="LangChain Server",version="1.0",description="A simple API server using LangChain's Runnable interfaces",
)# 第一个是服务器设置
# 第二个是模型的思考链路
# 第三个是是路由
add_routes(app,chain,path="/chain",
)if __name__ == "__main__":import uvicornuvicorn.run(app, host="localhost", port=8000)

执行

python serve.py

访问服务器

运行之后可以使用:http://localhost:8000/chain/playground/

或者可以设置客户端访问:

设置一个客户端,以便以编程方式与我们的服务进行交互。我们可以使用 [langserve.RemoteRunnable](/docs/langserve/#client).使用它,我们可以与服务链进行交互,就好像它在客户端运行一样。

client.py

from langserve import RemoteRunnableremote_chain = RemoteRunnable("http://localhost:8000/chain/")
remote_chain.invoke({"language": "italian", "text": "hi"})
python client.py

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/21607.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

XL7005A SOP-8 0.4A1.25-20V 150KHz降压直流转换器芯片

XL7005A作为一款高性能的降压型电源管理芯片,在智能家居中有着广泛的应用。以下是一些具体的案例: 1. 智能灯具:XL7005A可用于控制LED灯的电源,提供稳定高效的电源支持,确保灯具亮度稳定且无频闪,提高用户体…

springboot从2.7.2 升级到 3.3.0

文章目录 概要准备报错调整小结后记 概要 时代在进步,springboot已经来到了3.3.0 , 于是我们也打算升级下sbvadmin到3.3, jdk使用21的版本,下面是升级过程中碰到的一些问题,问题不大。 2.7.2 -> 3.3.0 准备 下载jdk21&#…

windows的软件修改图标

要修改一个可执行文件(.exe)的图标,你可以使用 Resource Hacker 这样的工具。Resource Hacker 是一个免费的资源编辑器,可以用于修改和编辑 Windows 可执行文件中的资源。 以下是一个简单的步骤来修改一个 .exe 文件的图标&#x…

shell脚本 字符串拼接变量赋值失效

问题现象: 代码如下: 执行结果: 可以看到data_dir属性是有值的,但是做字符串拼接变量赋值失效了很奇怪 怀疑赋值哪里写错了 问题分析: 1. 还是觉得赋值没有问题,手动显式赋值再执行下 执行结果&#…

职场如同“染缸”,老板只是给你个平台,染的好坏,全凭运气!

无论哪个单位,在职场大染缸里总有那么一拨同事是你喜欢的,也有那么一拨同事是不痛不痒的,还有那么一拨同事却是你怎么看都觉得不顺眼的。“不顺眼”的定义很宽泛,可能是他曾经的一些言论触及了你的道德底线,可能是他的…

C++数据结构之:堆Heap

摘要: it人员无论是使用哪种高级语言开发东东,想要更高效有层次的开发程序的话都躲不开三件套:数据结构,算法和设计模式。数据结构是相互之间存在一种或多种特定关系的数据元素的集合,即带“结构”的数据元素的集合&am…

【Qt】win10,QTableWidget表头下无分隔线的问题

1. 现象 2. 原因 win10系统的UI样式默认是这样的。 3. 解决 - 方法1 //横向表头ui->table->horizontalHeader()->setStyleSheet("QHeaderView::section{""border-top:0px solid #E5E5E5;""border-left:0px solid #E5E5E5;""bord…

Matlab|【重磅】配电网故障重构/孤岛划分

目录 1 主要内容 1.1 背景 1.2 流程图 2 部分代码 3 程序结果 4 下载链接 1 主要内容 程序主要复现《基于GA_BFGS算法的配电网故障恢复性重构研究_郑海广》,采用matlab编程软件实现,依据网络结构和DG供电方式对配电网进行孤岛划分,将含…

【算法训练记录——Day24】

Day24——回溯算法Ⅰ 77.组合 今日内容: ● 理论基础 ● 77. 组合 理论:代码随想录 77.组合 思路:k层for循环,不会 回溯,将组合问题抽象成n叉树,for循环控制宽度,递归的深度控制二叉树的深度 …

CSS学习笔记之高级教程(五)

23、CSS 媒体查询 - 实例 /* 如果屏幕尺寸超过 600 像素&#xff0c;把 <div> 的字体大小设置为 80 像素 */ media screen and (min-width: 600px) {div.example {font-size: 80px;} }/* 如果屏幕大小为 600px 或更小&#xff0c;把 <div> 的字体大小设置为 30px …

程序员的五大职业素养,你知道吗?

程序员职业生涯的挑战与机遇 在当今这个科技日新月异的时代&#xff0c;程序员作为技术行业的中坚力量&#xff0c;其职业生涯无疑充满了无数挑战与机遇。技术的快速迭代要求他们必须不断学习新知识、掌握新技能&#xff0c;以跟上时代的步伐。同时&#xff0c;云计算、人工智…

学习经验分享篇(1)——怎样将示波器数据(.CSV数据)导入Matlab/Simulink中并进行FFT分析(电机控制/电力电子方向必备技能)

最近比较忙&#xff0c;没怎么更新&#xff0c;后续打算不断出一些学习贴。 1.为什么要出这篇文章&#xff1f; &#xff08;1&#xff09;我当时第一次导示波器数据进入Matlab里面的时候&#xff0c;一直疯狂报错&#xff0c;搞了好久。 &#xff08;2&#xff09;好多同学现…

一点连接千家银行,YonSuite让“银行回单”一键获取

在当今日益复杂多变的商业环境中&#xff0c;企业的资金管理变得尤为重要。传统的银行回单管理方式&#xff0c;如手动登录网银、逐一下载回单、核对信息等&#xff0c;不仅效率低下&#xff0c;而且容易出错&#xff0c;给企业的财务管理带来了极大的挑战。 然而&#xff0c;…

【Pytorch】深入Pytorch模型的训练、log、可视化

文章目录 模型训练的模板综合案例-Pytorch 官网demo优化记录日志解析日志增加tensorboard数据记录保存训练曲线模型参数可视化增加wandb数据记录模型训练的模板 综合案例-Pytorch 官网demo pytorch 官网tutorial-quickstart https://blog.csdn.net/weixin_39107270/article/de…

安装 Android Studio 2024.1.1.6(Koala SDK35)和过程问题解决

记录更新Android Studio版本及适配Android V应用配置的一些过程问题。 安装包&#xff1a;android-studio-2024.1.1.6-windows.exe原版本&#xff1a;Android Studio23.2.1.23 Koala 安装过程 Uninstall old version 不会删除原本配置&#xff08;左下角提示&#xff09; Un…

YOLOv5改进 | 主干网络 | 将主干网络替换为轻量化的ShuffleNetv2【原理 + 完整代码】

&#x1f4a1;&#x1f4a1;&#x1f4a1;本专栏所有程序均经过测试&#xff0c;可成功执行&#x1f4a1;&#x1f4a1;&#x1f4a1; 目标检测是计算机视觉中一个重要的下游任务。对于边缘盒子的计算平台来说&#xff0c;一个大型模型很难实现实时检测的要求。基于一系列消融…

MQ之初识kafka

1. MQ简介 1.1 MQ的诞生背景 以前网络上的计算机&#xff08;或者说不同的进程&#xff09;传递数据&#xff0c;通信都是点对点的&#xff0c;而且要实现相同的协议&#xff08;HTTP、 TCP、WebService&#xff09;。1983 年的时候&#xff0c;有个在 MIT 工作的印度小伙突发…

前端开发记录

一.Node相关 镜像&#xff1a;registry "https://registry.npmmirror.com" 二.Eslint格式检查 关闭语法格式检查

【MySQL03】【 Buffer Pool】

文章目录 一、前言二、缓冲池&#xff08;Buffer Pool &#xff09;1. 缓冲池的概念2. LRU List、Free List 和 Flush List2.1 Free 链表2.1.1 缓冲页的哈希处理 2.2 Flush 链表2.3 LRU 链表2.3.1 简单 LRU 链表2.3.2 优化后的 LRU 列表2.3.3 更进一步的优化 3. 脏页的刷新4. 多…

B端产品无爆款,说有的都是忽悠和外行!

前言&#xff1a;网上经常有人讲运营&#xff0c;把C端那一套硬搬到B端&#xff0c;讲的自我陶醉&#xff0c;稍微有点常识的人就知道不能这么玩。 一、什么是B端和C端 B端&#xff08;Business-to-Business&#xff09;是指面向企业客户的市场和产品。B端产品或服务主要是为…