mirror of
https://github.com/ThearchyHelios/AgentLab.git
synced 2026-11-15 15:21:58 +00:00
941723b17c
- 身份与工具:登录页建第一个管理员(认人接口的 401 说明能不能建);搭建者有只读的人和组名录,选人给候选并核对名字;授权三行带标题;端点请求头名校验(空名、非法名存不进、发不出时说清原因);写入能力在工具页试运行一律演练、不发送,HTTP 状态照实说成败;写记忆不算只读、查询能力只能选同一端点上的只读能力;审批与遮罩的说法和实际规则一致;开登录时不要署名、导入和发布记登录的人;使用者不显示推演等只给搭建者的操作,403 按是否开登录说话;登录页只认一次人 - 流程与实例:图里用到的岗位(派给谁、超时升级给谁、发送确认派给谁)全部派生、没绑人的发布时报错;写外部系统的参数按能力声明的类型收拢后再算哈希和发送,收不成就不发;发起人的实例页只看这一步的状态,处理人才给待办卡;会签进度带登录核实和时间,升级后照实写规则;实例状态写流程的结论(已退回、未确认、等待核实写入结果),核实生效后不再挂失败原因;流程应用首页不派生最近封存运行的结果块,看板没数据时是安静的空态;样例⑩的金额带类型和下限、待办标题带金额,表单上下限前后端一起生效 - 看板与证据:定时任务模板加 ISO 周、上一 ISO 周、本月、上月;出处链穿过原样解析查询结果的整形节点,追不到原始数据的照实说停在哪里,样例⑨改用 cell();应用首页和版本历史都能做成应用;指标块单位不重复;版本列表带退役说明;定时任务页头跟着刷新;删视图要确认、新视图能起名;编辑器属性用中文名、术语带解释 - 指标出具(用户 2026-10-15 拍板):契约只写「指标来自」、上游没有报告撰写节点、成果里没有模型写的话时按指标出具——必需指标齐、指标输入追到原始数据、成果字段里的数回指得上才完整出具;受管级要求每个指标静态地追到原始数据(governed.metric_untraced);出具横幅和应用印章写明按指标 - 受管工作流降为已发布只给管理员(Q8 顺延,服务端同样拦);工作流接口带当前发布版的级别,画布上改过之后也认得出受管工作流
83 lines
2.7 KiB
Python
83 lines
2.7 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 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)
|
|
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}
|