Files
AgentLab/backend/app/tools/builtin/knowledge.py
ThearchyHelios 7739340607 普通用户建应用集成收尾:
- 问数据和个人应用的图放行绑定只读查询等合规工具的调用工具节点,只读和遮罩在这条路径上生效;被治理成写入的工具在只读运行里直接拒;知识库范围在工具层固定(图级默认值、参数名纠错、Agent 都改不了)
- 个人应用的刷新和个人蓝图的试运行只有拥有者能读:运行、事件、证据、工件、文件、运行与审批列表、对比、可验证报告、质询、假设分析、提取工作流一并收紧;个人蓝图的试运行不论谁发起都按个人应用约束
- 共享蓝图只给拥有者、对应应用的管理者、管理员,看不到的一律 404;审核副本归审核人;管理员看别人的个人应用只有元数据、可以归档
- 记录表跨版本汇总(只读挂载旧版本、按当前列 UNION ALL、各版本各自固定高水位,缺的版本照实写进印章);停用前发起的运行可以继续写旧版本;更正沿用原提交人、更正人记审计
- 约定收口:待办种类 review、事件 file.extracted、表单错误 file、模板定义带示例与预置;前端类型一次补齐、去掉临时的局部类型;审核待办卡不再给打不开的链接;读附件事件有中文说法;检查脚本补断言
2026-10-15 13:55:19 +08:00

88 lines
3.4 KiB
Python

from __future__ import annotations
from typing import Any
from pydantic import BaseModel, Field
from app.db.base import SessionLocal
from app.memory import kb, store
from app.tools.registry import ToolArgsError, ToolContext, register
class KbSearchArgs(BaseModel):
query: str = Field(description="检索问题")
limit: int = Field(default=5, ge=1, le=20)
collection: str | None = Field(default=None, description="限定知识库集合,留空则用节点配置的")
@register(
name="kb_search",
category="知识",
description="在知识库里做混合检索(向量 + 关键词),返回最相关的片段。",
args_schema=KbSearchArgs,
)
async def kb_search(ctx: ToolContext, **kwargs: Any) -> dict[str, Any]:
args = KbSearchArgs(**kwargs)
if ctx.fixed_scope and args.collection and args.collection != ctx.collection:
# 遮罩、只读的运行(使用者的问数据、个人应用、个人蓝图的试运行):知识库的内容不经遮罩,只能检索运行定下的那一个。
# 拒而不是悄悄改用默认的:检索的不是参数里写的那个库,结果却照常交回,看的人会当成查过了那一个
raise ToolArgsError(f"这次运行只能检索管理员设好的知识库,不能另指定知识库「{args.collection}」:"
"去掉 collection 参数即可")
async with SessionLocal() as session:
hits = await kb.search(
session,
collection=args.collection or ctx.collection,
query=args.query,
limit=args.limit,
)
return {"query": args.query, "hits": hits, "count": len(hits)}
class MemoryRecallArgs(BaseModel):
query: str = Field(description="想回忆什么")
limit: int = Field(default=5, ge=1, le=20)
@register(
name="memory_recall",
category="知识",
description="从长期记忆里取回与当前问题相关的内容。",
args_schema=MemoryRecallArgs,
)
async def memory_recall(ctx: ToolContext, **kwargs: Any) -> dict[str, Any]:
args = MemoryRecallArgs(**kwargs)
async with SessionLocal() as session:
hits = await store.recall(
session, scope=ctx.memory_scope, query=args.query, limit=args.limit
)
return {"scope": ctx.memory_scope, "memories": hits, "count": len(hits)}
class MemoryWriteArgs(BaseModel):
content: str = Field(description="要记住的内容,一条一个事实,写完整句子")
kind: str = Field(default="fact", description="fact | preference | episode")
importance: float = Field(default=0.5, ge=0.0, le=1.0)
@register(
name="memory_write",
category="知识",
description="把一条值得长期记住的信息写入记忆。相似内容会自动去重。",
args_schema=MemoryWriteArgs,
dangerous=False,
# 写的是平台自己的记忆:默认不用人确认,但不是只读
writes_state=True,
)
async def memory_write(ctx: ToolContext, **kwargs: Any) -> dict[str, Any]:
args = MemoryWriteArgs(**kwargs)
async with SessionLocal() as session:
item = await store.remember(
session,
scope=ctx.memory_scope,
content=args.content,
kind=args.kind,
importance=args.importance,
meta={"run_id": ctx.run_id, "node_id": ctx.node_id},
)
return {"id": item.id, "scope": item.scope, "saved": True}