【LangChain】langchain_core.tools.InjectedToolArg 类:工具调用参数运行时注入,而非由模型生成

langchain_core.tools.InjectedToolArg 是 LangChain 库中用于工具调用参数注入的注解类,隶属于 langchain_core.tools 模块。它主要用于标记工具函数中的参数,表示这些参数应由运行时上下文(如代理或链)自动注入,而不是由用户输入或模型直接提供。InjectedToolArg 是一个类型注解工具,通常结合 Annotated 类型(来自 Python 的 typing 模块)使用,增强工具函数的灵活性和可维护性。


langchain_core.tools.InjectedToolArg 的详细介绍

langchain_core.tools.InjectedToolArg 是 LangChain 框架中的一个重要功能,旨在增强工具参数的灵活性和安全性,特别是在处理运行时注入值时。本文将详细探讨其定义、使用方法、运行时注入机制以及相关需求。

1. 背景与定义

LangChain 是一个用于构建基于大语言模型(LLM)应用程序的框架,支持从提示管理到工具调用等功能。在工具调用场景中,有时需要将某些参数(如用户 ID)在运行时注入,而非由模型生成,以避免模型错误处理敏感信息或降低安全性。InjectedToolArg 正是为此设计的标记工具,允许开发者在工具定义中明确某些参数为运行时注入。

2. 使用方法

使用 InjectedToolArg 需要在工具定义中通过 Annotated 类型标注参数。以下是两种主要的使用方式:

2.1 使用 @tool 装饰器

直接在函数定义中标注参数。例如:

from langchain_core.tools import tool, InjectedToolArg
from typing import Annotated, List

@tool
def update_favorite_pets(pets: List[str], user_id: Annotated[str, InjectedToolArg]) -> None:
    """更新用户的收藏宠物。"""
    # 实现

在这里,user_id 被标记为注入参数,模型只需生成 pets 参数。

2.2 使用 Pydantic 模型

通过 args_schema 定义工具参数,也可以使用 InjectedToolArg。例如:

from langchain_core.tools import BaseTool
from pydantic import BaseModel, Field

class UpdateFavoritePetsSchema(BaseModel):
    """更新收藏宠物列表"""
    pets: List[str] = Field(..., description="要设置的收藏宠物列表。")
    user_id: Annotated[str, InjectedToolArg] = Field(..., description="用户 ID。")

@tool(args_schema=UpdateFavoritePetsSchema)
def update_favorite_pets(pets, user_id):
    user_to_pets[user_id] = pets

这展示了 InjectedToolArg 的灵活性,支持多种工具定义方式。

3. 对模式的影响

InjectedToolArg 对工具的输入和调用模式有显著影响:

  • 输入模式 (get_input_schema().schema()):包括所有参数,包括标记为注入的参数。
  • 工具调用模式 (tool_call_schema.schema()):排除标记为注入的参数,确保模型只生成非注入参数。

例如,在上述 update_favorite_pets 示例中,get_input_schema().schema() 会显示 petsuser_id,但 tool_call_schema.schema() 只包含 petsuser_id 被移除,模型无需生成它。

4. 运行时注入机制

运行时注入通常通过链式操作实现,修改工具调用以添加注入参数。以下是一个示例:

from langchain_core.runnables import chain

@chain
def inject_user_id(input):
    tool_call = input["tool_call"]
    user_id = input["user_id"]  # 假设 user_id 在输入中可用
    tool_call_copy = tool_call.copy()
    tool_call_copy["args"]["user_id"] = user_id
    return {"tool_call": tool_call_copy}

此链可与工具执行组合,确保在调用工具前正确添加 user_id。例如,模型生成的工具调用可能如下:

{
  "name": "update_favorite_pets",
  "args": {
    "pets": ["dog", "cat"]
  }
}

通过链式操作,user_id 被注入后变为:

{
  "name": "update_favorite_pets",
  "args": {
    "pets": ["dog", "cat"],
    "user_id": "12345"
  }
}

这确保模型不处理敏感信息,安全性得到提升。

5. 完整代码示例


import getpass
import os

from langchain.chat_models import init_chat_model
from typing import List
from langchain_core.tools import InjectedToolArg, tool
from typing_extensions import Annotated

from copy import deepcopy
from langchain_core.runnables import chain

# 导入和设置 API 密钥
if not os.environ.get("OPENAI_API_KEY"):
    os.environ["OPENAI_API_KEY"] = getpass.getpass("Enter API key for OpenAI: ")

llm = init_chat_model("gpt-4o-mini", model_provider="openai")

user_to_pets = {}

# 使用 InjectedToolArg 注解来标记工具的某些参数
@tool(parse_docstring=True)
def update_favorite_pets(
    pets: List[str], user_id: Annotated[str, InjectedToolArg]
) -> None:
    """添加最喜欢的宠物列表。

    Args:
        pets: 要设置的最喜欢的宠物列表。
        user_id: 用户的 ID。
    """
    user_to_pets[user_id] = pets

@tool(parse_docstring=True)
def delete_favorite_pets(user_id: Annotated[str, InjectedToolArg]) -> None:
    """删除最喜欢的宠物列表。

    Args:
        user_id: 用户的 ID。
    """
    if user_id in user_to_pets:
        del user_to_pets[user_id]

@tool(parse_docstring=True)
def list_favorite_pets(user_id: Annotated[str, InjectedToolArg]) -> None:
    """列出最喜欢的宠物(如果有)。

    Args:
        user_id: 用户的 ID。
    """
    return user_to_pets.get(user_id, [])


# 查看这些工具的输入模式,会发现 user_id 仍然列在
print(update_favorite_pets.get_input_schema().schema())

"""
输出:
{
  "description": "Add the list of favorite pets.",
  "properties": {
    "pets": {
      "description": "List of favorite pets to set.",
      "items": {"type": "string"},
      "title": "Pets",
      "type": "array"
    },
    "user_id": {
      "description": "User's ID.",
      "title": "User Id",
      "type": "string"
    }
  },
  "required": ["pets", "user_id"],
  "title": "update_favorite_petsSchema",
  "type": "object"
}
"""

# 查看工具调用模式(即传递给模型用于工具调用的模式),会发现 user_id 已被移除
print(update_favorite_pets.tool_call_schema.schema())

"""
输出:
{
  "description": "Add the list of favorite pets.",
  "properties": {
    "pets": {
      "description": "List of favorite pets to set.",
      "items": {"type": "string"},
      "title": "Pets",
      "type": "array"
    }
  },
  "required": ["pets"],
  "title": "update_favorite_pets",
  "type": "object"
}
"""


# 调用工具时,需要手动传入 user_id:
user_id = "123"
update_favorite_pets.invoke({"pets": ["lizard", "dog"], "user_id": user_id})
print(user_to_pets)
print(list_favorite_pets.invoke({"user_id": user_id}))

"""
输出:
{'123': ['lizard', 'dog']}
['lizard', 'dog']
"""


#当模型调用工具时,不会生成 user_id 参数
tools = [
    update_favorite_pets,
    delete_favorite_pets,
    list_favorite_pets,
]
llm_with_tools = llm.bind_tools(tools)
ai_msg = llm_with_tools.invoke("my favorite animals are cats and parrots")
print(ai_msg.tool_calls)

"""
输出:
[{'name': 'update_favorite_pets',
  'args': {'pets': ['cats', 'parrots']},
  'id': 'call_pZ6XVREGh1L0BBSsiGIf1xVm',
  'type': 'tool_call'}]
"""


# 在运行时注入参数:如果我们想使用模型生成的工具调用来实际执行工具,需要自己注入 user_id:
@chain
def inject_user_id(ai_msg):
    tool_calls = []
    for tool_call in ai_msg.tool_calls:
        tool_call_copy = deepcopy(tool_call)
        tool_call_copy["args"]["user_id"] = user_id
        tool_calls.append(tool_call_copy)
    return tool_calls

print(inject_user_id.invoke(ai_msg))

"""
输出:
[{'name': 'update_favorite_pets',
  'args': {'pets': ['cats', 'parrots'], 'user_id': '123'},
  'id': 'call_pZ6XVREGh1L0BBSsiGIf1xVm',
  'type': 'tool_call'}]
"""


# 现在,我们可以将模型、注入代码和实际工具链在一起,创建一个执行工具的链
tool_map = {tool.name: tool for tool in tools}

@chain
def tool_router(tool_call):
    return tool_map[tool_call["name"]]

chain = llm_with_tools | inject_user_id | tool_router.map()
response = chain.invoke("my favorite animals are cats and parrots")
print(response)

"""
输出:
[ToolMessage(content='null', name='update_favorite_pets', tool_call_id='call_oYCD0THSedHTbwNAY3NW6uUj')]
"""


# 查看 `user_to_pets` 字典,可以看到它已更新为包含cats和parrots:
print(user_to_pets)

"""
输出:
{'123': ['cats', 'parrots']}
"""

以下是注解工具参数的几种替代方式:

方法 1
from langchain_core.tools import BaseTool
from pydantic import BaseModel, Field

class UpdateFavoritePetsSchema(BaseModel):
    """更新最喜欢的宠物列表"""
    pets: List[str] = Field(..., description="List of favorite pets to set.")
    user_id: Annotated[str, InjectedToolArg] = Field(..., description="User's ID.")

@tool(args_schema=UpdateFavoritePetsSchema)
def update_favorite_pets(pets, user_id):
    user_to_pets[user_id] = pets

update_favorite_pets.get_input_schema().schema()

输出:

{
  "description": "Update list of favorite pets",
  "properties": {
    "pets": {
      "description": "List of favorite pets to set.",
      "items": {"type": "string"},
      "title": "Pets",
      "type": "array"
    },
    "user_id": {
      "description": "User's ID.",
      "title": "User Id",
      "type": "string"
    }
  },
  "required": ["pets", "user_id"],
  "title": "UpdateFavoritePetsSchema",
  "type": "object"
}
update_favorite_pets.tool_call_schema.schema()

输出:

{
  "description": "Update list of favorite pets",
  "properties": {
    "pets": {
      "description": "List of favorite pets to set.",
      "items": {"type": "string"},
      "title": "Pets",
      "type": "array"
    }
  },
  "required": ["pets"],
  "title": "update_favorite_pets",
  "type": "object"
}
方法 2
from typing import Optional, Type

class UpdateFavoritePets(BaseTool):
    name: str = "update_favorite_pets"
    description: str = "Update list of favorite pets"
    args_schema: Optional[Type[BaseModel]] = UpdateFavoritePetsSchema

    def _run(self, pets, user_id):
        user_to_pets[user_id] = pets

UpdateFavoritePets().get_input_schema().schema()

输出:

{
  "description": "Update list of favorite pets",
  "properties": {
    "pets": {
      "description": "List of favorite pets to set.",
      "items": {"type": "string"},
      "title": "Pets",
      "type": "array"
    },
    "user_id": {
      "description": "User's ID.",
      "title": "User Id",
      "type": "string"
    }
  },
  "required": ["pets", "user_id"],
  "title": "UpdateFavoritePetsSchema",
  "type": "object"
}
UpdateFavoritePets().tool_call_schema.schema()

输出:

{
  "description": "Update list of favorite pets",
  "properties": {
    "pets": {
      "description": "List of favorite pets to set.",
      "items": {"type": "string"},
      "title": "Pets",
      "type": "array"
    }
  },
  "required": ["pets"],
  "title": "update_favorite_pets",
  "type": "object"
}
方法 3
class UpdateFavoritePets2(BaseTool):
    name: str = "update_favorite_pets"
    description: str = "Update list of favorite pets"

    def _run(self, pets: List[str], user_id: Annotated[str, InjectedToolArg]) -> None:
        user_to_pets[user_id] = pets

UpdateFavoritePets2().get_input_schema().schema()

输出:

{
  "description": "Use the tool.\n\nAdd run_manager: Optional[CallbackManagerForToolRun] = None\nto child implementations to enable tracing.",
  "properties": {
    "pets": {
      "items": {"type": "string"},
      "title": "Pets",
      "type": "array"
    },
    "user_id": {
      "title": "User Id",
      "type": "string"
    }
  },
  "required": ["pets", "user_id"],
  "title": "update_favorite_petsSchema",
  "type": "object"
}
UpdateFavoritePets2().tool_call_schema.schema()

输出:

{
  "description": "Update list of favorite pets",
  "properties": {
    "pets": {
      "items": {"type": "string"},
      "title": "Pets",
      "type": "array"
    }
  },
  "required": ["pets"],
  "title": "update_favorite_pets",
  "type": "object"
}

6. 需求与注意事项

使用 InjectedToolArg 需要满足以下条件:

  • 版本要求:需要 langchain-core>=0.2.21,可通过 pip install -qU "langchain[openai]" 安装。
  • 安装:确保环境配置正确,特别是在使用 OpenAI 模型时。

7. 实际应用与社区反馈

InjectedToolArg 广泛用于代理和工具调用场景,特别是在不暴露给 LLM 的情况下传递运行时参数。它在 2024 年 8 月被添加到 LangChain 中,解决了许多开发者的需求。社区反馈表明其功能强大,但开发者应注意版本兼容性问题,并通过链式操作实现注入。

8. 总结

InjectedToolArg 是 LangChain 中处理运行时注入参数的重要工具,特别适合安全性和灵活性要求高的场景。开发者应确保使用最新版本,并通过链式操作实现注入。

内容概要:《2025年机器身份安全现状报告》揭示了机器身份安全在全球企业中的重要性和面临的挑战。随着云计算、AI和微服务的发展,机器身份数量已远超人身份,成为现代网络安全的核心。然而,管理这些身份变得越来越复杂,许多组织缺乏统一的管理策略。77%的安全领导者认为每个未发现的机器身份都是潜在的风险点,50%的组织在过去一年中经历了与机器身份相关的安全事件,导致应用发布延迟、客户体验受损和数据泄露等问题。AI的兴起进一步加剧了这一问题,81%的安全领导者认为机器身份将是保护AI未来的关键。此外,证书相关故障频发,自动化管理仍不足,量子计算的威胁也逐渐显现。面对这些挑战,组织需要建立全面的机器身份安全计划,重点加强自动化、可见性和加密灵活性。 适合人群:从事信息安全、IT管理和技术架构规划的专业人士,尤其是关注机器身份管理和云原生环境安全的从业者。 使用场景及目标:①理解机器身份在现代企业安全架构中的关键作用;②识别当前机器身份管理中存在的主要风险和挑战;③探讨如何通过自动化、可见性和加密灵活性来提升机器身份安全管理的有效性;④为制定或优化企业机器身份安全策略提供参考。 其他说明:此报告基于对全球1,200名安全领导者的调查,强调了机器身份安全的重要性及其在未来几年内可能面临的复杂变化。报告呼吁各组织应重视并积极应对这些挑战,以确保业务连续性和数据安全。
<think>好的,我现在需要帮助用户了解如何将生成的图数据存储到Neo4j数据库中,特别是使用Neo4jGraph或Neo4jVector这两个工具。首先,我得确认用户的需求是什么。用户可能已经生成了图数据,现在需要将这些数据导入到Neo4j中,但可能不清楚具体步骤和工具的使用方法。 首先,我应该回想一下Neo4j的基本操作。Neo4j是一个图数据库,通常使用Cypher查询语言来操作数据。用户提到的Neo4jGraph和Neo4jVector可能是指某些库或工具,用于简化与Neo4j的交互。例如,在Python中,可能有相关的库如py2neo或官方提供的neo4j驱动,但用户提到的这两个名称可能属于特定的框架,比如LangChain中的组件?因为我知道LangChain有Neo4jGraph和Neo4jVector的集成,用于处理知识图谱和向量嵌入。 接下来,我需要确定用户使用的是哪种编程语言和环境。假设是Python,因为Neo4jGraph和Neo4jVector常见于Python生态中。用户可能已经通过某种方式生成了图数据,比如节点和关系,现在需要将这些数据存储到Neo4j中。 首先,用户需要安装必要的库。比如,安装langchain库,或者直接使用neo4j的Python驱动。可能需要同安装几个包,比如langchain_community中的相关模块,或者neo4j的官方驱动。 然后,用户需要连接到Neo4j数据库。这通常需要URI、用户名和密码。需要确保Neo4j实例正在运行,并且用户有正确的访问权限。 接下来,使用Neo4jGraph来存储图数据。这里可能需要将节点和关系转换成Cypher语句,或者利用库提供的API来添加数据。比如,使用add_graph方法,或者通过执行Cypher命令来创建节点和关系。 对于Neo4jVector,这可能涉及到将向量数据存储到Neo4j中,用于支持向量搜索。比如,存储文本的嵌入向量,并建立索引以便进行相似性搜索。这可能需要使用特定的方法,如from_existing_graph来从现有图结构中创建向量索引,或者from_texts来直接导入文本和向量。 在步骤中,可能需要示例代码来说明如何连接数据库、创建图对象、添加数据以及关闭连接。同,需要注意异常处理和资源释放,比如正确关闭驱动连接。 此外,用户可能需要了解如何验证数据是否成功导入,比如在Neo4j浏览器中执行MATCH查询来检查节点和关系是否存在。 还需要考虑性能优化,比如批量插入数据而不是逐条插入,以提高效率。同,索引的创建对于查询性能也很重要,特别是当处理大规模数据。 最后,用户可能会有疑问,比如如何处理复杂的图结构,或者如何将现有数据转换为适合Neo4j的格式。可能需要提醒用户确保数据模型的正确性,节点和关系的属性是否合理,以及是否需要建立索引或约束来优化查询。 总结一下,回答应该包括以下几个部分: 1. 环境准备:安装必要的库和配置Neo4j连接。 2. 使用Neo4jGraph存储图结构数据,包括节点和关系。 3. 使用Neo4jVector存储向量数据,支持向量搜索。 4. 示例代码和验证步骤。 5. 注意事项和常见问题。</think>以下是使用$Neo4jGraph$和$Neo4jVector$存储图数据到Neo4j数据库的分步指南: ### 一、环境准备 1. 安装Python依赖库: ```bash pip install neo4j langchain langchain-community ``` 2. 启动Neo4j数据库并获取连接信息: - 默认URI:$bolt://localhost:7687$ - 用户名/密码:$neo4j/your_password$ ### 二、使用Neo4jGraph存储图结构 ```python from langchain_community.graphs import Neo4jGraph # 创建连接 graph = Neo4jGraph( url="bolt://localhost:7687", username="neo4j", password="your_password" ) # 定义图数据(节点+关系) cypher_query = ''' CREATE (a:Person {name: 'Alice'}), (b:Person {name: 'Bob'}), (a)-[:FRIEND]->(b) ''' # 执行写入操作 graph.query(cypher_query) # 验证数据 result = graph.query("MATCH (p:Person) RETURN p.name") print(result) # 输出[{'p.name': 'Alice'}, {'p.name': 'Bob'}] # 关闭连接 graph.driver.close() ``` ### 三、使用Neo4jVector存储向量数据 ```python from langchain_community.vectorstores import Neo4jVector from langchain_openai import OpenAIEmbeddings # 创建向量存储 vector_store = Neo4jVector.from_texts( texts=["机器学习导论", "图数据库原理"], embedding=OpenAIEmbeddings(), url="bolt://localhost:7687", username="neo4j", password="your_password", index_name="knowledge_base", node_label="Document" ) # 执行向量搜索 results = vector_store.similarity_search("人工智能基础") print(results[0].page_content) # 输出"机器学习导论" ``` ### 四、最佳实践 1. 批量写入优化:使用$UNWIND$语句实现批量插入 ```cypher UNWIND $batch AS row CREATE (n:Node {id: row.id}) ``` 2. 索引加速:创建索引提高查询性能 ```python graph.query("CREATE INDEX FOR (n:Person) ON (n.name)") ``` 3. 数据验证:通过Neo4j Browser执行$MATCH (n) RETURN n LIMIT 25$可视化验证
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

彬彬侠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值