当前位置: 首页 > news >正文

LangGraph--基础学习(工具调用)

本节将详细学习大模型是怎么调用工具的,为什么可以调用工具等等,手写一个工具调用,后续可以通过mcp自己调用即可,没必要自己写,但是学习过程中需要手写,通常怎么使用第三方工具调用呢?


import os  
from langchain_community.tools.tavily_search import TavilySearchResults  def _set_env(var: str, value):  if not os.environ.get(var):  os.environ[var] = value  _set_env("TAVILY_API_KEY", "tvly-xxxx")  tool = TavilySearchResults(max_results=4)
tool.invoke("苏超谁赢了?")
[{'title': '美团、京东、饿了么组团借势苏超,这把谁赢了?','url': 'https://www.digitaling.com/articles/1369073.html','content': '![数英网 DIGITALING](https://file.digitaling.com/images/common/logo.@2x.png "数英网 DIGITALING")\n\n# 美团、京东、饿了么组团借势苏超,这把谁赢了?\n\n![](https://file.digitaling.com/images/common/loading.gif)\n\n![](https://file.digitaling.com/images/common/loading.gif)\n\n扫描,分享朋友圈\n\n#### **美团、**京东、**饿了么,** **这相爱(**或许爱得不多?**)相杀的三巨头,又!又!又!把火烧到了苏超的绿茵场。**\n\n就是那个真·草根真·热血、球迷互喷、“没有假球,只有世仇”的江苏省城市足球联赛!\n\n从电商到外卖,从补贴大战到谐音梗对轰,这三家如今在球场上短兵相接,狭路相逢,商业宿命感直接拉满。 [...] **![1750304708326761.jpg](https://file.digitaling.com/images/common/loadimg.gif "1750304708326761.jpg")**\n\n![1750304708326761.jpg](https://file.digitaling.com/images/common/loadimg.gif "1750304708326761.jpg")\n\n**宿迁  \n赢了干杯,输了也干杯!  \n霸王敬酒,洋河大曲喝到美。**\n\n![1750237167666583.jpg](https://file.digitaling.com/images/common/loadimg.gif "1750237167666583.jpg")\n\n![1750237167666583.jpg](https://file.digitaling.com/images/common/loadimg.gif "1750237167666583.jpg")\n\n**苏州  \n江苏的苏是苏州的苏。  \n大闸蟹的蟹,是阳澄湖的蟹。** [...] 打开数英App  \n进入【我的】右上角扫一扫登录\n\n![扫码登录](https://www.digitaling.com/file/qrImg/login/3a51ce918d87b6dd7f97ef719ee90164.png "打开数英App扫一扫登录")\n\n其他登录\n\n选择收藏夹\n\n![](https://file.digitaling.com/creator/images/collection_default.jpg)\n\n上传封面\n\n建议封面尺寸为400x400像素,\n\n仅支持JPG/PNG静态图片\n\n**资料更新成功!**\n\n[查看人才库](https://www.digitaling.com/jobs/talent)[取消](javascript:void(0);)\n\n![]()\n![肉墩墩老师](https://file.digitaling.com/eImg/avatar/10012046/20240411142137_63547_320.jpg "肉墩墩老师")','score': 0.7625837},{'title': '面对面|敬一丹:“苏超”不管谁赢江苏都赢了 - 扬子晚报','url': 'https://www.yangtse.com/news/bzxc/202506/t20250619_224004.html','content': '... 苏超”,敬一丹表示:“江苏的苏超太引人注目,太欢乐了,我觉得这是一个特别值得琢磨的事,现在不管是哪个城市赢,我觉得江苏都赢了。” 扬子晚报|紫牛','score': 0.7395922}]

大模型如果只依赖自身的知识,那么很难流行起来,也不会解决太多的问题,因为大模型自身的训练数据是有限的,像 agent 系统之所以能够流行,主要依赖大模型的决策能力,以前我们如果写程序,需要程序员按照产品经理的产品设计,设置好代码的运行逻辑依次的按照产品逻辑进行执行,比如用户询问北京的天气,那么会通过一定的代码比如关键词匹配,正则表达式或者NLP相关的工具来判断出用户的意图,还有分析出想要查询的地区是北京,然后调用相应的工具获取数据,过程中会有很大的出错概率,如参数分析的不准确,工具调用的不正确等,现在有了大模型,我们可以利用大模型的意图分析能力准确的得到需要调用哪个工具以及调用参数。

LangGraph 中可以利用LangChain 中的tool call 功能来实现工具的调用,本文先介绍一下在LangChain 中如何使用 tool call, 然后再使用LangGraph 工作流中调用工具。

上面是工具自身的调用,并不需要大模型,就像是普通的 python 函数调用,只是这里的函数需要按照一定的规则进行定义。然后使用工具的invoke 方法来真正的调用工具。

二、自定义工具¶

由于langchain_community 中的工具很多我们是用不了的,所以这里我们来封装一个自定义工具,使用高德的天气查询接口来做一个天气查询的工具。高德的天气查询接口文档请查阅 基础 API 文档-开发指南-Web服务 API | 高德地图API

2.1 工具类的定义¶

参考 TavilySearchResults 工具的实现以及 LangChain 官方的 tools 文档 How to create tools | 🦜️🔗 LangChain , 我这里使用继承自BaseTool 的方式来实现。

主要的流程包括

  1. 继承langchain_core.tools.BaseTool 类
  2. 定义几个属性,
    • name: 工具的名字。
    • description: 工具的描述,这里的描述很重要,越详细越准确越好,后面的大模型是需要根据这里的描述来判断要调用哪个工具。
    • args_schema: 参数的定义,pydantic.BaseModel 类型,这里也需要对函数调用的参数进行详细的描述,越准确越好。
    • 除了上面几个属性,如果工具还需要自己单独的属性,也需要在类里定义,如这个天气api 需要的api_key。
  3. 定义 _run 方法,实现真正的业务调用逻辑, 如果需要使用异步调用,则需要再定义 _arun 方法。

根据上面的规则,定义如下的查询天气 tool。

import json  
from typing import Type  
import requests  
from langchain_core.tools import BaseTool  
from pydantic import BaseModel, Field  class GaoDeWeatherInput(BaseModel):  city: str = Field(description="要查询天气的城市名称")  class GaoDeWeather(BaseTool):  """  高德天气查询  """    name: str = "高德天气查询"  description: str = "高德天气查询,输入城市名,返回该城市的天气情况,例如:北京"  args_schema: Type[BaseModel] = GaoDeWeatherInput  api_key: strdef _run(self, city):  s = requests.session()  api_domain = 'https://restapi.amap.com/v3'  url = f"{api_domain}/config/district?keywords={city}"f"&subdistrict=0&extensions=base&key={self.api_key}"  headers = {"Content-Type": "application/json; charset=utf-8"}  city_response = s.request(method='GET', headers=headers, url=url)  City_data = city_response.json()  if city_response.status_code == 200 and City_data.get('info') == 'OK':  if len(City_data.get('districts')) > 0:  CityCode = City_data['districts'][0]['adcode']  weather_url = f"{api_domain}/weather/weatherInfo?city={CityCode}&extensions=all&key={self.api_key}"  weatherInfo_response = s.request(method='GET', url=weather_url)  weatherInfo_data = weatherInfo_response.json()  if weatherInfo_response.status_code == 200 and weatherInfo_data.get('info') == 'OK':  contents = []  if len(weatherInfo_data.get('forecasts')) > 0:  for item in weatherInfo_data['forecasts'][0]['casts']:  content = {}  content['date'] = item.get('date')  content['week'] = item.get('week')  content['dayweather'] = item.get('dayweather')  content['daytemp_float'] = item.get('daytemp_float')  content['daywind'] = item.get('daywind')  content['nightweather'] = item.get('nightweather')  content['nighttemp_float'] = item.get('nighttemp_float')  contents.append(content)  s.close()  return contents  else:  return "没有查询到该城市的天气信息"  weather_tool = GaoDeWeather(api_key='xxxx')  result = weather_tool.invoke("安徽")  
print(json.dumps(result, ensure_ascii=False, indent=4))
[{"date": "2025-06-21","week": "6","dayweather": "大雨","daytemp_float": "23.0","daywind": "东南","nightweather": "小雨","nighttemp_float": "18.0"},{"date": "2025-06-22","week": "7","dayweather": "多云","daytemp_float": "25.0","daywind": "东南","nightweather": "多云","nighttemp_float": "18.0"},{"date": "2025-06-23","week": "1","dayweather": "多云","daytemp_float": "26.0","daywind": "东","nightweather": "阴","nighttemp_float": "19.0"},{"date": "2025-06-24","week": "2","dayweather": "晴","daytemp_float": "28.0","daywind": "东","nightweather": "阴","nighttemp_float": "20.0"}
]

由于高德的天气接口需要传入城市的cityCode, 并不是城市名称,所以先要获取一下城市的citycode,再根据 citycode 获取气象数据。

调用上面自定义的天气查询接口得到如上输出

该形式可以针对任何你想调用的api,其实就是研究官方的web服务接口,解析数据就行了

上面的工具可以很好的运行,也成功获取到了天气数据,当我们在调用工具的时候,需要输入城市名的,但是用户在交互过程中,很难知道用户是怎么问的,如用户可能问

  • 北京明天的天气如何?
  • 上海后天会下雨吗?
  • 我在浙江,晚上出门需要带雨伞吗?

当遇到这些问题时,传统的业务流程很难做到准确的分析调用,这时我们就需要使用大模型来分析规划调用哪个工具,以及调用工具时的参数。

接下来我们看一下如何使用大模型来调用。

weather_tool = GaoDeWeather(api_key='xxxx')  
tools = [weather_tool] 
# 定义一个工具名称和工具实例的字典,用于之后的工具调用
tools_by_name = {tool.name: tool for tool in tools} 
# 将工具与大模型进行绑定
llm_with_tools = llm.bind_tools(tools)  # 还没有引入langgraph,所以需要人工调用工具,后面使用引入langgraph加入节点和边就可以直接调用了
messages = [HumanMessage(content="安徽明天的天气如何?")]  
result = llm_with_tools.invoke(messages)  
messages.append(result)  
outputs = []  
if result.tool_calls:  for tool_call in result.tool_calls:  tool_name = tool_call.get("name")  if tool_name in tools_by_name:  tool = tools_by_name[tool_name]  tool_result = tool.invoke(tool_call.get("args"))  tool_message = ToolMessage(  content=json.dumps(tool_result, ensure_ascii=False),  name=tool_call["name"],  tool_call_id=tool_call["id"],  )  messages.append(tool_message)  outputs.append(tool_result)  final_result = llm_with_tools.invoke(messages)  print(final_result.content)  outputs.append(final_result)
city =  安徽
[ToolMessage(content='[{"date": "2025-06-21", "week": "6", "dayweather": "大雨", "daytemp_float": "23.0", "daywind": "东南", "nightweather": "小雨", "nighttemp_float": "18.0"}, {"date": "2025-06-22", "week": "7", "dayweather": "多云", "daytemp_float": "25.0", "daywind": "东南", "nightweather": "多云", "nighttemp_float": "18.0"}, {"date": "2025-06-23", "week": "1", "dayweather": "多云", "daytemp_float": "26.0", "daywind": "东", "nightweather": "阴", "nighttemp_float": "19.0"}, {"date": "2025-06-24", "week": "2", "dayweather": "晴", "daytemp_float": "28.0", "daywind": "东", "nightweather": "阴", "nighttemp_float": "20.0"}]', name='get_current_weather', tool_call_id='call_0_a9c4ef6b-7548-4dc2-927b-9dce4e258029')]

上面的代码当第一次使用 result = llm_with_tools.invoke("北京明天的天气如何?") 调用大模型时,此时大模型如果判断出要使用某个工具时,那么会返回如下的数据

注意到返回的数据中有个 tool_calls 字段,这是一个列表,因为有时候大模型可能分析出要调用多个工具,但是大多数情况下只有一个工具,并将调用这个工具的参数放到 args 里返回了。如上面的调用,告诉客户端,需要调用一个叫 高德天气查询 的工具,参数为 {"city": "安徽"} , 当客户端拿到大模型的分析输出时,就会使用 tool.invoke(tool_call.get("args")) 来真正的进行工具调用。当得到工具的输出以后,将结果保存在 outputs 列表中,此时如果我们直接将工具的输出返回给用户,只是一堆json 数据,并没有真正回答用户的问题,所以这里还需要再次调用大模型,将用户的问题(北京明天的天气如何?)和工具的输出再次传给大模型,让大模型进行总结回答。

这里需要将之前的用户消息和ai返回的消息以及调用工具返回的消息放到一个列表里,最后再统一调用一次大模型。

 上面的代码后面的if就是为了拿到数据,调用工具,拿到内容后再调用大模型,让其总结返回结果:

  1. 初始化一个messages 来存放消息
  2. result = llm_with_tools.invoke(messages) 为第一次调用大模型,用于让大模型分析要调用哪个工具以及调用工具时的参数。
  3. tool_result = tool.invoke(tool_call.get("args")) 为真正的调用工具,得到工具的输出。
  4. tool_message = ToolMessage(content=json.dumps(tool_result, ensure_ascii=False)) 为定义tool_message, 之后使用messages.append(tool_message)将工具的输出也放到消息列表里
  5. final_result = llm_with_tools.invoke(messages) 为最终调用大模型,根据用户的提问以及大模型的输出做最终的解答

得到的输出为:

city =  安徽
安徽明天的天气情况如下:- **白天天气**: 多云
- **白天温度**: 25°C
- **白天风向**: 东南风
- **夜间天气**: 多云
- **夜间温度**: 18°C请注意天气变化,合理安排出行!

四、LangGraph 调用工具¶

上面铺垫了这么多,终于进入了主题,如何在LangGraph 中调用工具? 我们来回顾总结一下上面langchain 进行工具调用的流程

  1. 定义工具,写清楚工具的描述和参数的描述信息
  2. 初始化大模型,并将工具绑定到大模型中
  3. 拿到用户的提问,进行第一次的大模型调用,得到大模型分析出来的需要调用哪个工具以及对应的参数
  4. 根据大模型返回的工具信息真正的执行工具调用
  5. 将之前的用户问题,AI的回答以及工具的输出再次发给大模型,得到最终的输出结果

这里有一些注意的地方,首先,大模型并不是每次都能返回工具调用的参数,如果用户的问题和工具一毛钱关系都没有,则大模型也是不会返回工具调用信息的,如用户问 "iphone 16 多少钱", 这个问题很明显和这个天气查询工具一点关系都没有,则大模型会直接回答问题。其次,大模型有时会返回多个工具调用,需要依次进行工具调用,虽然多数情况下只会返回一个工具调用。

清楚了LangChain 的工具调用,我们使用 LangGraph 来实现一下 。

  1. 初始化一个带有工具调用的大模型client
  2. 添加一个大模型调用节点(node),用于和大模型进行交互
  3. 当需要进行工具调用时,进行工具调用,此时需要一个条件路由函数
  4. 如果需要调用工具,则将工具调用的结果和之前的用户消息大模型消息再次请求一次大模型,得到的结果再次进行是否需要工具调用判断,也就是每次进行大模型调用都需要判断一下是否还需要工具调用
  5. 如果不需要进行工具调用,则直接将大模型生成的恢复返回给用户,结束工作流
  6. 整个graph 过程中的消息放到State 中进行节点之间的共享

得到的流程如下

参考这张图,chatbot 节点有两条虚线分别连接 tools 节点和 END 节点,虚线表示的是条件边,对应代码中的 add_conditional_edges,后面可能会走哪条分支,实线是确定的走向,对应代码为add_edge, 如 tools 节点之后确定要走chatbot 节点。

这里有一个很巧妙的设计,上面说过,工具调用结束以后,需要再次调用大模型对问题进行总结回答,这里的大模型调用没有在工具函数中定义,而是通过 LangGraph 的普通边来实现。

上面的代码定义了两个运行节点,一个是chatbot, 使用 chatbot 函数定义,另外一个是使用BasicToolNode 类定义的类节点,如果不明白可以查看前面的文章。

import json  
from typing import Type, TypedDict, Annotated  
import requests  
from langchain_core.messages import ToolMessage, HumanMessage, AIMessage  
from langchain_core.tools import BaseTool  
from langgraph.graph import add_messages, StateGraph, START, END  
from pydantic import BaseModel, Field  
from langchain_openai import ChatOpenAI  class State(TypedDict):  messages: Annotated[list, add_messages]  # 上面的代码都创建了,我这边注释了
# class GaoDeWeatherInput(BaseModel):  
#     city: str = Field(description="要查询天气的城市名称")  # class GaoDeWeather(BaseTool):  
#     """  
#     高德天气查询,和上面的代码一样  
#     """    
#     ...weather_tool = GaoDeWeather(api_key='XX')  # llm = ChatOpenAI(  
#     model_name="qwen-turbo",  
#     temperature=0.7,  
#     max_tokens=1024,  
#     top_p=1,  
#     openai_api_key="sk-xxxx",  
#     openai_api_base="https://dashscope.aliyuncs.com/compatible-mode/v1"  
# )  tools = [weather_tool]  
llm_with_tools = llm.bind_tools(tools)  # 大模型执行节点  
def chatbot(state: State):  return {"messages": [llm_with_tools.invoke(state["messages"])]}  # 工具执行节点  
class BasicToolNode:  """A node that runs the tools requested in the last AIMessage."""  # 这里是我们自定定义的适配langgraph的工具节点,后续可以直接使用langgraph的节点对象即可def __init__(self, tools: list) -> None:  self.tools_by_name = {tool.name: tool for tool in tools}  # 拿出工具名称def __call__(self, inputs: State):  messages = inputs.get("messages", [])  # 拿出数据if messages:  message = messages[-1]  # 拿出最新的数据else:  raise ValueError("No message found in input")  outputs = []  for tool_call in message.tool_calls:  tool_result = self.tools_by_name[tool_call["name"]].invoke(  tool_call["args"]  )  # 把工具函数和参数绑定进行执行,得到结果json化,然后存储outputs.append(  ToolMessage(  content=json.dumps(tool_result),  name=tool_call["name"],  tool_call_id=tool_call["id"],  )  )  return {"messages": outputs}  # 定义一个条件节点  
def condition_tools(state: State):  ai_message = state["messages"][-1]  if ai_message.tool_calls:  return "tools"  return END  # 构建 graph 
graph_builder = StateGraph(State)  # 添加节点  
graph_builder.add_node("chatbot", chatbot)  
graph_builder.add_node("tools", BasicToolNode(tools))  # 添加边  
graph_builder.add_edge(START, "chatbot")  
graph_builder.add_conditional_edges("chatbot", condition_tools,{"tools": "tools",   # 条件返回的字符串 → 目标节点END: END,})  
graph_builder.add_edge("tools", "chatbot")  app = graph_builder.compile()  app.get_graph().draw_mermaid_png(output_file_path="graph_tool.png")  inputs = {"messages": [HumanMessage(content="安徽合肥后天的天气")]}  result = app.invoke(inputs)  
print(result.get("messages")[-1].content)
city =  合肥
安徽合肥后天的天气情况如下:- **日期**: 2025-06-23(星期一)
- **白天天气**: 多云
- **白天温度**: 26°C
- **白天风向**: 东风
- **夜间天气**: 阴
- **夜间温度**: 19°C请注意天气变化,合理安排出行!

总结:

        学习是个循序渐进的过程,不要指望一下子就学会了,多写代码,多思考,虽然现在可以直接让大模型写就行了,但是前提你需要理解这个,否则后面有问题都不知道咋回事

相关文章:

LangGraph--基础学习(工具调用)

本节将详细学习大模型是怎么调用工具的,为什么可以调用工具等等,手写一个工具调用,后续可以通过mcp自己调用即可,没必要自己写,但是学习过程中需要手写,通常怎么使用第三方工具调用呢? import o…...

华为云 Flexus+DeepSeek 实战:华为云单机部署 Dify-LLM 开发平台全流程指南【服务部署、模型配置、知识库构建全流程】

华为云 FlexusDeepSeek 实战:华为云单机部署 Dify-LLM 开发平台全流程指南【服务部署、模型配置、知识库构建全流程】 文章目录 华为云 FlexusDeepSeek 实战:华为云单机部署 Dify-LLM 开发平台全流程指南【服务部署、模型配置、知识库构建全流程】前言1、…...

【appium】2.初始连接脚本配置

连接配置 from appium import webdriver desired_caps {platformName: Android,automationName: UIAutomator2,deviceName: ZTEB880,appPackage: com.taobao.taobao,appActivity: com.taobao.tao.welcome.Welcome,noReset: True }driver webdriver.Remote(http://localhost:…...

磁性传感器在电机控制闭环系统中的反馈作用

磁性传感器的基本原理和类型 基本原理 :磁性传感器是基于磁学原理来检测磁场强度、方向或其他与磁场相关的物理量。常见的磁性传感器有霍尔传感器、磁阻传感器等。霍尔传感器是利用霍尔效应工作的,当电流通过置于磁场中的半导体材料时,在垂直…...

Python:.py文件如何变成双击可执行的windows程序?(版本1)

1、如下.py文件,右键重命名文件后缀名:py改为:pyw 2、修改时,提示如下:不用管点击:是即可 3、之后双击,即可执行python代码文件。 好的,我们来详细介绍一下 Python 的 .pyw 文件。 简…...

Spring Boot + MyBatis + Vue:全栈开发的深度剖析与实践指南

一、技术栈深度剖析 (一)Spring Boot:后端开发的加速器 Spring Boot 是基于 Spring 框架的一个开源 Java 项目,旨在简化基于 Spring 的应用开发。它通过自动配置机制,能够根据项目中添加的依赖自动配置 Spring 和相关…...

学习C++、QT---03(C++的输入输出、C++的基本数据类型介绍)

每日一言 你比想象中更强大,那些咬牙坚持的瞬间,都在雕刻更好的你。 案例:C的输入输出 但是我也会用c语言的方式来回顾c语言的写法,因为两种语言都是密不可分的,所以不能忘记,所以两个一起写 注意点&#…...

八、Redis的主从原理、哨兵

简介: 想要了解Redis的主从原理,首先得认识一个基本的分布式理论-CAP理论。要理解这个理论,其实也非常简单。 CAP理论 C:Consistency、A:Available、P:Partition tolerance 。这是CAP三个字母的全称。C&…...

springboot通过独立事务管理器实现资源隔离与精准控制​

安心流转站核心业务模块,为什么!我们考虑这样设计,下面讲讲专用事务管理器的设计与必要性​! 一、为什么需要专属事务管理器?​​ 在安心流转站模块中,存在 ​​「多资源混合操作」​​ 和 ​​「业务高敏…...

59-Oracle 10046事件-知识准备

上一篇说到了autotrace,SQL调试时候的获取性能和参数数据,直接用上trace,还有个更全能的工具10046。是不是很多小伙伴会对这么个数字,觉得起名很奇怪,数字起名任性。“10046”本质是Oracle内核事件的随机性技术编号&am…...

2025年渗透测试面试题总结-2025年HW(护网面试) 03(题目+回答)

安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 目录 2025年HW(护网面试) 03 1. 同源策略(Same-Origin Policy) 2. XSS攻击用途 3. XSS类…...

嵌入式开发之嵌入式系统硬件架构设计时,如何选择合适的微处理器/微控制器?

在嵌入式系统硬件架构设计中,选择合适的微处理器 / 微控制器(MCU/MPU)是关键环节,需从多维度综合评估。以下是系统化的选择策略及核心考量因素: 一、明确应用需求与核心指标 1. 性能需求 处理能力:根据任…...

C++(面向对象编程——继承)

继承基础概念 1.什么是继承? 继承是C三大特性之一;继承是一个已经存在的类的基础上新建一个类,新建的类拥有已经存在的类的特性。主要提现的是代码复用的思想。新的类继承了基类的所有成员变量和成员函数,包括不显示的函数&…...

Unity Shader开发-着色器变体(2)-定义着色器变体

一.定义着色器变体 定义一个着色器变体(Shader Variant)从概念和实现上讲,主要包括以下几个核心部分 1.使用预编译指令来声明变体关键字 关键字是驱动变体生成的“开关”。它们是简单的字符串标识符,用于在 Shader 代码中标记不…...

Cookie和Session的作用和区别

Cookie 客户端持久化保存服务器数据的一种机制(持久化存储就是存硬盘里)。Cookie文件数据为键值对形式,客户端根据服务器域名的不同分别存储Cookie,不同域名的Cookie不同,不会产生冲突。 典型应用场景: 保…...

Redis集群部署终极指南:架构选型、生产部署与深度优化

第一部分:Redis集群技术全景解析 1.1 Redis集群演进史 单机时代(2009-2012):Redis 2.8之前,纯单机模式复制时代(2012-2015):Redis 2.8引入PSYNC改进复制哨兵时代(2015-…...

腾讯云IM即时通讯:开启实时通信新时代

一、引言 在当今数字化浪潮席卷全球的时代,即时通讯已然成为互联网世界中不可或缺的关键元素。无论是个人日常生活中的社交互动,还是企业运营里的高效协作,即时通讯都发挥着举足轻重的作用,已然渗透到人们生活与工作的每一个角落…...

基于Qt的UDP主从服务器设计与实现

概述 一个基于Qt框架实现的UDP主从服务器系统,该系统具备自动主机选举、故障转移和状态同步等关键功能,适用于分布式能源管理系统中的设备通信与协调。 系统核心功能 1. 自动主机选举与故障转移 系统通过优先级机制实现自动主机选举,当主机…...

JVM(8)——详解分代收集算法

JVM 的分代收集算法不是一种具体的垃圾收集算法实现,而是一种指导思想和设计原则,是现代 JVM 垃圾收集器的基石。其核心思想源于对程序运行过程中对象生命周期分布的观察(即弱分代假说)。 核心思想与理论基础:分代假说…...

深入Java面试:从Spring Boot到微服务

深入Java面试:从Spring Boot到微服务 在准备互联网大厂的Java岗位面试时,掌握核心技术栈是关键。本文将从技术栈中选取几个重要的技术点进行探讨,帮助你在面试中脱颖而出。 问题一:Spring Boot的核心特性是什么? 面…...

【软考高级系统架构论文】论无服务器架构及其应用

论文真题 近年来,随着信息技术的迅猛发展和应用需求的快速更迭,传统的多层企业应用系统架构面临越来越多的挑战,已经难以适应这种变化。在这一背景下,无服务器架构(Serverless Architecture) 逐渐流行,它强调业务逻辑由事件触发,具有短暂的生命周期,运行于无状态的轻量…...

Snapchat矩阵运营新策略:亚矩阵云手机打造高效社交网络

1. Snapchat平台特性与风控挑战​​ Snapchat作为全球领先的即时社交平台,其独特的阅后即焚功能和强社交属性使其风控系统极为严格: ​​核心风控机制​​ ​​设备指纹检测​​:记录设备ID、系统版本、IP地址等硬件信息​​行为模式分析​…...

BGP路由反射器(RR)实验详解,结尾有详细脚本

目录 路由反射器基础概念 实验拓扑与设计 实验配置步骤 配置验证与排错 实验总结 完整配置命令集 路由反射器基础概念 在传统的IBGP网络中,为了防止路由环路,BGP规定通过IBGP学到的路由不能再传递给其他IBGP对等体,这导致所有IBGP路由…...

【JAVA】数组的使用

文章目录 前言一、数组的基本概念1.1 数组的创建和初始化1.2 数组的基本使用 二、数组是引用类型2.1 初始JVM的内存分布JVM内存划分(按功能分区) 2.2 基本类型变量与引用类型变量的区别2.3 再谈引用变量2.4 认识null 三、数组作为函数的参数和返回值四、…...

Python的6万张图像数据集CIFAR-10和CIFAR-100说明

CIFAR-10和CIFAR-100数据集是8000万张微小图像数据集的标记子集。CIFAR-10和CIFAR-100都是由AlexKrizhevsky、VinodNair和GeoffreyHinton创建。数据集说明的网页:https://www.cs.toronto.edu/~kriz/cifar.html 一、CIFAR-10数据集 (一)CIFA…...

CTF--PhP Web解题(走入CTF)

前情提要 分享有趣CTF题目&#xff0c;记录学习过程 题目&#xff08;带注释,方便理解&#xff09; <?php // 开启PHP源代码高亮显示&#xff0c;输出当前文件内容&#xff08;用于调试/展示&#xff09; highlight_file(__FILE__);// 关闭所有错误报告&#xff0c;防止敏感…...

【Linux仓库】进程概念与基本操作【进程·贰】

&#x1f31f; 各位看官好&#xff0c;我是&#xff01; &#x1f30d; Linux Linux is not Unix &#xff01; &#x1f680; 今天来学习Linux中进程概念与基本操作。 &#x1f44d; 如果觉得这篇文章有帮助&#xff0c;欢迎您一键三连&#xff0c;分享给更多人哦&#xff01…...

Z-Ant开源程序是简化了微处理器上神经网络的部署和优化

​一、软件介绍 文末提供程序和源码下载 Z-Ant &#xff08;Zig-Ant&#xff09; 是一个全面的开源神经网络框架&#xff0c;专门用于在微控制器和边缘设备上部署优化的 AI 模型。Z-Ant 使用 Zig 构建&#xff0c;为资源受限的硬件上的模型优化、代码生成和实时推理提供端到端…...

面试题-在ts中类型转换的方法

在 TypeScript 中&#xff0c;类型转换主要分为 类型断言&#xff08;Type Assertion&#xff09;、类型守卫&#xff08;Type Guard&#xff09; 和 类型兼容转换 三种方式。以下是详细分类和示例&#xff1a; 一、类型断言&#xff08;Type Assertion&#xff09; 强制编译…...

【论文笔记】【强化微调】T-GRPO:对视频数据进行强化微调

tulerfeng/Video-R1: Video-R1: Reinforcing Video Reasoning in MLLMs [&#x1f525;the first paper to explore R1 for video] 1. 引述 在强化微调中&#xff0c;像 GRPO、DAPO 这样的方法都是对文本或者图片进行微调思考&#xff0c;所以这类微调方法不对时序信息做处理&…...

`shallowReactive` 与 `shallowRef`:浅层响应式 API

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》、《前端求职突破计划》 &#x1f35a; 蓝桥云课签约作者、…...

使用Node.js开发服务端接口

Node.js是一个基于JavaScript的运行时环境&#xff0c;非常适合开发高性能的服务端接口。以下是开发服务端接口的主要方法和步骤。 选择合适的框架 Express、Koa或Fastify是Node.js中常用的框架。Express是最流行的选择&#xff0c;适合快速开发。Koa更轻量&#xff0c;适合需…...

`teleport` 传送 API 的使用:在 Vue 3 中的最佳实践

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》、《前端求职突破计划》 &#x1f35a; 蓝桥云课签约作者、…...

Linux 多种方式实现行转列

目录 一. 前提二. xargs 实现行转列三. paste 实现行转列四. sed 实现行转列 一. 前提 ⏹之前在这下面篇文章中使用sed命令实现了行专列&#xff0c;本篇文章再介绍几种更加简单的方式。 Linux sed案例 &#x1f449; 20231126-2.log 110120 SPLREQUEST 内容1 AAA memberID1…...

AI与SEO关键词协同进化

内容概要 人工智能&#xff08;AI&#xff09;与搜索引擎优化&#xff08;SEO&#xff09;的结合&#xff0c;正深刻变革着关键词策略的制定与执行方式。本文旨在探讨AI技术如何驱动SEO关键词领域的智能化进化&#xff0c;核心在于利用AI强大的数据处理与模式识别能力&#xf…...

C# 网络编程-关于HTTP/HTTPS的基础(一)

一、HTTP基础概念 1. 请求-响应模型 HTTP是基于客户端-服务器的无状态协议&#xff0c;流程如下&#xff1a; 客户端&#xff08;如浏览器&#xff09;发起请求。服务器接收请求并处理。服务器返回响应&#xff0c;包含状态码、Header和响应体。连接关闭&#xff0c;后续请求…...

题解:P11501 [ROIR 2019] 探险队(Day 2)

前言&#xff1a;这道题 dp 做法找环的部分还没有用拓扑做的&#xff0c;补充一下。 这道题其实很像“上司的舞会”&#xff0c;就是求树上最大独立集。 这里我们把每个人向他讨厌的那个人连边&#xff08;发现所有点出度均为 1 1 1&#xff0c;所以这是一个基环树&#xff0…...

读者写者问题与读写锁自旋锁

一、读者写者问题 读者写者问题具有以下特点&#xff1a; 一个交易场所---写者写入数据&#xff0c;读者读数据两种角色---读者&#xff0c;写者三种关系 读者和读者---并发写者和写者---互斥读者和写者---互斥 && 同步 二、读者写者VS生产消费 生产者消费者模型中…...

Sublime text启用vim

打开&#xff1a;首选项 > 设置&#xff0c;在打开的输入框中把 "ignored_packages": ["Vintage"] 修改为 "ignored_packages": []&#xff0c;不忽略Vintage&#xff0c;即为启用Vintage&#xff0c;它是Sublime的内置vim插件。 然后再添加&…...

蚂蚁百宝箱快速创建智能体AI小程序

蚂蚁百宝箱官网https://tbox.alipay.com/community?operationSource1006/ 以下是一篇关于蚂蚁百宝箱快速创建智能体 AI 小程序的图文并茂的博客&#xff1a; 标题&#xff1a;蚂蚁百宝箱快速创建智能体 AI 小程序&#xff0c;开启智能应用新体验 引言 在数字化飞速发展的当…...

【Anconda安装教程】安装到环境配置全流程

目录 前言 一、进入官网下载 二、下载Anconda​编辑 三、安装Anconda 四、配置环境变量 五、验证是否安装成功 六、anaconda的使用 情况一&#xff1a;电脑现在没有装python或者现在装的可以卸载掉 情况二&#xff1a;电脑目前装了python&#xff0c;但想保留它 6.1 进…...

Linux系统编程 | IPC对象---信号量

在前面两篇博客文章中&#xff0c;对Linux系统编程部分IPC三大对象中的消息队列和共享内存的知识体系做了一个大致的梳理&#xff0c;在本篇文章中&#xff0c;将对三大IPC对象中的最后一个信号量做一个总结。如果有需要的博客朋友&#xff0c;可以参考我的Linux系统编程专栏参…...

当数据自己会说话:聚类与分类算法全景解析

从金融风控到医疗诊断&#xff0c;两种机器学习技术如何重塑决策逻辑 在人工智能与数据驱动的时代&#xff0c;聚类和分类作为机器学习的两大核心技术&#xff0c;已成为从海量数据中提取价值的必备工具。它们看似相似——都是将数据划分到不同的组中——但内在逻辑和应用场景却…...

哈佛结构(Harvard Architecture)与冯·诺依曼架构(Von Neumann Architecture)

一、基础概念与历史溯源 哈佛结构 起源&#xff1a;1940年代由哈佛大学开发的Mark I计算机首次采用&#xff0c;专为弹道计算优化。核心特征&#xff1a; 物理分离的存储器&#xff1a;程序指令存储在ROM/Flash&#xff0c;数据存储在RAM&#xff0c;两者独立编址。独立总线系统…...

Python内存使用分析工具深度解析与实践指南(下篇)

文章目录 引言6. guppy3 / Heapy功能安装程序示例适用场景注意事项 7. objgraph功能安装程序示例适用场景注意事项 8. memory_profiler功能安装程序示例适用场景注意事项 9. profile&#xff08;标准库&#xff09;功能程序示例适用场景注意事项 总结对比表 引言 在Python编程…...

经典控制理论:线性化笔记

一、弹簧阻尼系统 求B点的位置X0&#xff0c;与弹簧形变后的位置X1的关系 ---- 解&#xff1a; 二、直流电动机模型 求输出转速与输入电压的关系 解&#xff1a;...

【StarRocks系列】查询优化

步骤参考官网 分析查询 | StarRocks StarRocks-Profile分析及优化指南 StarRocks-Profile分析及优化指南 - 经验教程 - StarRocks中文社区论坛...

【STM32】STM32的中断系统寄存器NVIC、EXTI

文章目录 中断概述中断的概念为什么需要中断STM32的中断 STM32的中断体系架构NVICNVIC的介绍中断优先级优先级寄存器优先级组 EXTI 中断概述 中断的概念 在主程序运行过程中&#xff0c;出现了特定事件&#xff0c;使得CPU暂停当前正在运行的程序&#xff0c;转而去处理这个事…...

LLM-201: OpenHands与LLM交互链路分析

一、核心交互链路架构 #mermaid-svg-ZBqCSQk1PPDkIXNx {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-ZBqCSQk1PPDkIXNx .error-icon{fill:#552222;}#mermaid-svg-ZBqCSQk1PPDkIXNx .error-text{fill:#552222;strok…...

税务 VR 虚拟体验,带来全新办税感受

在过去&#xff0c;企业办税难题诸多。申报纳税高峰期&#xff0c;办税服务厅人满为患&#xff0c;财务人员需早起取号排队&#xff0c;耗费大量时间。传统办税流程复杂&#xff0c;涉及多环节和部门&#xff0c;资料繁多&#xff0c;若准备不全或有误就得重新准备&#xff0c;…...