城乡建设网站证件查询wordpress windows linux
城乡建设网站证件查询,wordpress windows linux,创意设计网站公司,外贸怎么做网站引言
随着大语言模型逐步具备“理解—推理—行动”的能力#xff0c;如何让模型稳定、可控地调用外部工具#xff0c;已成为构建智能体#xff08;Agent#xff09;系统的关键一环。相比早期基于文本协议的工具调用方式#xff0c;OpenAI 推出的 Function Calling#x…引言随着大语言模型逐步具备“理解—推理—行动”的能力如何让模型稳定、可控地调用外部工具已成为构建智能体Agent系统的关键一环。相比早期基于文本协议的工具调用方式OpenAI 推出的Function CallingTools机制为模型与程序世界之间建立了一套结构化、可验证的交互接口。本文将从工程实践出发完整展示一个OpenAI 兼容 Function Calling 智能体的实现过程从消息协议Message、模型封装ChatOpenAI、工具抽象Tool到支持多轮、多工具调用的 Agent 主循环设计。通过真实的搜索与计算场景示例你将看到模型如何在最少提示干预的情况下自主规划、调用工具并整合结果最终给出可靠答案。如果你希望构建一个可扩展、可调试、可流式演进的 Agent 系统本文的实现将是一个坚实的起点。代码 veroMessage类为了兼容OpenAI的消息格式我们重写一下Message类fromtypingimportDict,Any,Optional,List,Self,Union,LiteralimporttimefrompydanticimportBaseModel,FieldclassMessage(BaseModel):content:Optional[Union[str,List[Dict[str,Any]]]]Nonerole:Literal[system,user,assistant,tool]name:Optional[str]Nonetool_call_id:Optional[str]Nonetool_calls:Optional[List[Dict[str,Any]]]Nonetimestamp:intField(default_factorylambda:int(time.time()))metadata:Dict[str,Any]Field(default_factorydict,descriptiontoken counts)classmethoddefuser(cls,content:str,**kw)-Self:returncls(roleuser,contentcontent,**kw)classmethoddefsystem(cls,content:str,**kw)-Self:returncls(rolesystem,contentcontent,**kw)classmethoddefassistant(cls,content:Optional[str]None,tool_calls:List[dict]None,**kw)-Self:returncls(roleassistant,contentcontent,tool_callstool_calls,**kw)classmethoddeftool(cls,content:str,tool_call_id:str,**kw)-Self:returncls(roletool,contentcontent,tool_call_idtool_call_id,**kw,)defto_dict(self)-Dict[str,Any]:d{k:vfork,vinself.__dict__.items()ifknotin(timestamp,metadata)andvisnotNone}returndChatOpenAI类同时我们封装了工具调用的入参和出参就像上篇文章中介绍的一样fromtypingimportOptional,Iterator,List,Union,Dict,AnyfromopenaiimportOpenAIfrom.messageimportMessagefromvero.configimportsettingsfromvero.core.exceptionsimportLLMCallError,LLMConfigErrorclassChatOpenAI: 基于 OpenAI Python SDK 的聊天模型封装用于与对话式 LLM 进行交互。 属性: model_name: 使用的 LLM 模型名称。 temperature: 文本生成的采样温度。 max_tokens: 单次响应的最大 token 数。 timeout: 请求超时时间秒。 api_key: OpenAI API Key。 base_url: OpenAI API Base URL。 def__init__(self,model_name:Optional[str]None,api_key:Optional[str]None,base_url:Optional[str]None,temperature:float0.7,max_tokens:Optional[int]None,timeout:Optional[int]None,**kwargs,)-None: 初始化 LLM 封装类。 如果未显式传入参数则回退到配置文件中的默认值。 Raises: LLMConfigError: 当缺少 api_key、base_url 或 model_name 时抛出。 self.model_namemodel_nameorsettings.model_nameprint(f Initializing LLM with model:{self.model_name})self.temperaturetemperature self.max_tokensmax_tokens self.timeouttimeoutorgetattr(settings,timeout,None)self.kwargskwargs self.api_keyapi_keyorsettings.openai_api_key self.base_urlbase_urlorsettings.openai_base_urlifnotall([self.api_key,self.base_url,self.model_name]):raiseLLMConfigError(Missing api_key, base_url, or model_name for LLM client)self._clientself._create_client()def_create_client(self)-OpenAI: 创建并返回 OpenAI 客户端实例。 returnOpenAI(api_keyself.api_key,base_urlself.base_url,timeoutself.timeout,)defgenerate(self,messages:List[Union[Message,dict]],stream:boolFalse,temperature:Optional[float]None,tools:Optional[List[dict]]None,tool_choice:Optional[Union[str,Dict[str,Any]]]None,**kwargs,)-Union[Message,Iterator[str]]: 调用 LLM 生成响应支持流式输出与非流式完整输出。 Args: messages: 对话历史消息列表可以是 Message 对象或原始 dict。 stream: 是否启用流式输出为 True 时返回一个迭代器。 temperature: 可选参数用于覆盖默认 temperature。 tools: OpenAI Tool / Function Calling 的 schema 定义。 tool_choice: 工具选择策略auto、none 或指定工具。 **kwargs: 其他 OpenAI 参数如 max_tokens。 Returns: Message: 非流式场景下返回 Assistant Message。 若模型触发了工具调用tool_calls 会挂载在 Message 上 此时 content 可能为 None。 Iterator[str]: 流式模式下按 token / chunk 迭代返回生成文本。 Raises: LLMCallError: 当 LLM API 调用失败时抛出。 # 将 Message 对象统一转换为 OpenAI API 可接受的 dict 结构messages_dict[msg.to_dict()ifisinstance(msg,Message)elsemsgformsginmessages]try:# 构造基础请求参数payload{model:self.model_name,messages:messages_dict,temperature:temperatureorself.temperature,max_tokens:kwargs.get(max_tokens,self.max_tokens),}# 如果提供了 tools / tool_choice则注入到请求中iftools:payload[tools]toolsiftool_choice:payload[tool_choice]tool_choice# 透传其他 OpenAI 支持的参数fork,vinkwargs.items():ifknotin{temperature,max_tokens}:payload[k]v responseself._client.chat.completions.create(streamstream,**payload,)ifstream:# 使用内部生成器封装流式响应# 避免整个 generate 方法本身变成 generatordef_stream_generator():forchunkinresponse:contentchunk.choices[0].delta.contentorifcontent:yieldcontentreturn_stream_generator()# -----------------------------# 非流式模式构造 Message 对象# -----------------------------resp_msgresponse.choices[0].message usageresponse.usageor{}assistant_msgMessage.assistant(contentresp_msg.content,metadata{usage:{prompt_tokens:usage.prompt_tokens,completion_tokens:usage.completion_tokens,total_tokens:usage.total_tokens,}},)# 处理 Function / Tool Calling 结果如果存在ifresp_msg.tool_calls:assistant_msg.tool_calls[{id:call.id,type:function,function:{name:call.function.name,arguments:call.function.arguments,},}forcallinresp_msg.tool_calls]returnassistant_msgexceptExceptionase:# 统一封装为自定义异常便于上层处理raiseLLMCallError(fLLM call failed:{str(e)})fromeTool类主要增加to_openai_schema()方法可以转换为上篇文章看到的OpenAI兼容的JSON Schema定义importinspectfromtypingimportAny,Dict,List,Optional,Union,get_origin,get_argsclassTool: 表示一个可被 LLM 智能体系统调用的工具函数封装。 该 Tool 同时支持 1. 人类可读的描述name / description 2. Python 直接调用__call__ 3. OpenAI Function Calling Schema # Python 类型到 JSON Schema 类型的映射PYTHON_TO_JSON{str:string,int:integer,float:number,bool:boolean,dict:object,list:array,}def__init__(self,name:str,description:str,func:callable,arguments:list,outputs:str,):self.namename self.descriptiondescription self.funcfunc self.argumentsarguments# [(param_name, type_str, default), ...]self.outputsoutputs# 同时保留 signature方便生成 Function Calling schemaself.signatureinspect.signature(func)def__call__(self,*args,**kwargs): 直接调用底层的 Python 函数 returnself.func(*args,**kwargs)defto_string(self)-str: 返回一个人类可读的工具描述字符串主要用于调试或日志 args_str, .join([f{n}:{t}(f {d}ifdisnotNoneelse)for(n,t,d)inself.arguments])return(fTool Name:{self.name}, fDescription:{self.description}, fArguments:{args_str}, fOutputs:{self.outputs})# # OpenAI Function Calling# defto_openai_schema(self)-dict: 将当前 Tool 转换为 OpenAI / Qwen 兼容的 Function Calling Schema。 返回格式示例 { type: function, function: { name: ..., description: ..., parameters: { type: object, properties: {...}, required: [...] } } } properties:Dict[str,Any]{}required:List[str][]forname,paraminself.signature.parameters.items():ifnameself:continueannotationparam.annotation defaultNoneifparam.defaultisinspect._emptyelseparam.default schema,is_requiredself._annotation_to_schema(annotation,default)# OpenAI 要求每个参数都有 descriptionschema[description]name properties[name]schemaifis_required:required.append(name)parameters{type:object,properties:properties,required:required,# 如果你希望严格模式可打开# additionalProperties: False,}return{type:function,function:{name:self.name,description:self.descriptionor,parameters:parameters,},}def_annotation_to_schema(self,annotation:Any,default:Any): 将 Python 类型注解转换为 JSON Schema并判断参数是否必填 originget_origin(annotation)argsget_args(annotation)# Optional[T] 或 Union[T, None] → 非必填iforiginisUnionandtype(None)inargs:non_none[aforainargsifaisnottype(None)]iflen(non_none)1:inner_schema,_self._annotation_to_schema(non_none[0],None)return{anyOf:[inner_schema,{type:null}]},False# List[T]iforiginin(list,List):item_typeargs[0]ifargselseAny item_schema,_self._annotation_to_schema(item_type,None)return{type:array,items:item_schema,},defaultisNone# Dict[str, T]iforiginin(dict,Dict):value_typeargs[1]iflen(args)2elseAny value_schema,_self._annotation_to_schema(value_type,None)return{type:object,additionalProperties:value_schema,},defaultisNone# 基础类型ifannotationinself.PYTHON_TO_JSON:return{type:self.PYTHON_TO_JSON[annotation]},defaultisNone# 兜底无法识别的类型统一视为 stringreturn{type:string},defaultisNonedeftool(func): 装饰器将普通 Python 函数转换为 Tool 对象。 自动解析 - 函数名 - 参数名 / 类型 / 默认值 - 返回值类型 - 函数 docstring 作为工具描述 signatureinspect.signature(func)arguments[]# 解析参数信息主要用于人类可读forparaminsignature.parameters.values():annotationparam.annotation type_str(annotation.__name__ifhasattr(annotation,__name__)elsestr(annotation))defaultNoneifparam.defaultisinspect._emptyelseparam.default arguments.append((param.name,type_str,default))# 解析返回值类型return_annotationsignature.return_annotationifreturn_annotationisinspect._empty:outputsNoneelse:outputs(return_annotation.__name__ifhasattr(return_annotation,__name__)elsestr(return_annotation))descriptioninspect.getdoc(func)or未提供工具描述namefunc.__name__returnTool(namename,descriptiondescription,funcfunc,argumentsarguments,outputsoutputs,)Function Calling 智能体终于可以进入本文的主题我们实现一个通过Function Calling进行工具调用的智能体。如果看完了最近的几篇文章理解下面的代码应该不难importjsonimporttimefromtypingimportOptional,List,Dict,Anyfromvero.toolimportToolfromvero.core.messageimportMessagefromvero.core.chat_openaiimportChatOpenAIfromvero.core.agentimportAgentfromvero.core.exceptionsimportToolNotFoundErrorclassOpenAIFunctionAgent(Agent): 一个支持 OpenAI 兼容 Function Callingtools的 Agent 实现。 特性 - 支持在单个 assistant 消息中包含多个 tool_calls - 自动执行模型请求的工具 - 将工具执行结果自动注入回对话上下文 - 持续循环直到模型输出最终的纯文本答案 def__init__(self,name:str,llm:ChatOpenAI,tools:Optional[List[Tool]]None,system_prompt:Optional[str]None,max_turns:int5,tool_choice:strauto,)-None: 初始化 OpenAIFunctionAgent。 参数 name: Agent 的可读名称标识。 llm: 用于推理的 ChatOpenAI 实例。 tools: 可选的 Tool 列表表示 Agent 可调用的工具。 system_prompt: 可选的 system prompt 覆盖文本。 max_turns: 最大推理 / 工具执行循环次数。 tool_choice: OpenAI 的 tool_choice 参数auto、none 或强制指定工具。 print(f Initializing OpenAIFunctionAgent {name} ...)super().__init__(namename,llmllm,toolstools,system_promptsystem_prompt,max_turnsmax_turns,)self.tool_choicetool_choice self.tools_schemaself._build_tool_schemas()print(f️ Registered tools:{self.tools})print(f⚙️ Tool choice mode:{self.tool_choice})# 使用 system prompt 初始化对话历史self.add_message(Message.system(self._build_system_prompt()))# ------------------------------------------------------------------# System prompt# ------------------------------------------------------------------def_build_system_prompt(self)-str: 构建 Agent 使用的 system prompt。 return(self.system_promptorYou are an intelligent agent capable of using external tools to help solve user queries.)# ------------------------------------------------------------------# Tool schemas# ------------------------------------------------------------------def_build_tool_schemas(self)-List[Dict[str,Any]]: 将已注册的 Tool 转换为 OpenAI 兼容的 function calling schema。 ifnotself.tools:return[]return[t.to_openai_schema()fortinself.tools]# ------------------------------------------------------------------# Main execution loop# ------------------------------------------------------------------defrun(self,user_query:str)-str: 执行 Agent 的主推理循环。 执行步骤 1. 将用户输入追加到对话历史 2. 携带工具 schema 调用 LLM 3. 如果 assistant 返回了 tool_calls - 逐个执行工具 - 将工具结果以 Message.tool 的形式注入历史 4. 重复以上过程直到模型返回纯文本结果 print(\n)print(f User Input:{user_query})print(\n)self.add_message(Message.user(user_query))forturn_idxinrange(1,self.max_turns1):print(f Turn{turn_idx}/{self.max_turns})assistant_msg:Messageself.llm.generate(messagesself._history,toolsself.tools_schema,tool_choiceself.tool_choice,)print(f LLM Assistant Message | fcontent{assistant_msg.content!r}, ftool_calls{bool(assistant_msg.tool_calls)})self.add_message(assistant_msg)# -------------------------------------------------# 情况 A最终文本回复无工具调用# -------------------------------------------------ifnotassistant_msg.tool_calls:print( 未检测到工具调用返回最终答案。\n)returnassistant_msg.contentor# -------------------------------------------------# 情况 B检测到工具调用# -------------------------------------------------fortcinassistant_msg.tool_calls:functc[function]tool_namefunc[name]args_textfunc[arguments]tool_call_idtc[id]print(f 检测到工具调用 → fname{tool_name}, id{tool_call_id}, raw_args{args_text})# 解析参数OpenAI 保证 arguments 为 JSON 字符串try:argsjson.loads(args_text)print( 工具参数解析成功。)exceptExceptionase:print(f❌ 工具参数解析失败:{e})args{}# 查找工具对象tool:Tool|Noneself.tool_by_names.get(tool_name)ifnottool:print(❌ 未找到对应工具)raiseToolNotFoundError(fUnknown tool:{tool_name})# 执行工具print(f 执行工具 {tool_name}参数{args})try:starttime.perf_counter()outputtool(**args)costtime.perf_counter()-startprint(f 工具输出:{output}| ⏱️ 耗时:{cost:.3f}s)exceptExceptionase:outputfTool execution failed:{e}print(f 工具执行失败:{e})# 将工具结果注入回对话历史print( 将工具结果注入对话历史。)self.add_message(Message.tool(contentstr(output),tool_call_idtool_call_id,))# 继续下一轮让模型基于工具结果继续推理raiseRuntimeError(已达到 max_turns但仍未生成最终答案)函数调用智能体实战importtimefromvero.coreimportChatOpenAI,Agentfromvero.agentsimportSimpleAgent,OpenAIFunctionAgentfromvero.tool.buildinimportmath_evaluate,duckduckgo_searchfromvero.configimportsettingsdefrun_agent(agent_class:Agent,input_text:str,max_turns5):llmChatOpenAI()agent:Agentagent_class(test-agent,llm,tools[duckduckgo_search,math_evaluate],max_turnsmax_turns,)returnagent.run(input_text)if__name____main__:settings.model_nameQwen/Qwen3-30B-A3B-Instruct-2507starttime.perf_counter()answerrun_agent(OpenAIFunctionAgent,2025年12月13日为止国内票房最高的三部动画片是什么导演分别是谁,)print(f Final LLM Answer:{answer}\n)print(f⏳ Elapsed:{time.perf_counter()-start:.1f}s) Initializing LLM with model: Qwen/Qwen3-30B-A3B-Instruct-2507 Initializing OpenAIFunctionAgent test-agent ... ️ Registered tools: [Tool duckduckgo_search, Tool math_evaluate] ⚙️ Tool choice mode: auto User Input: 2025年12月13日为止国内票房最高的三部动画片是什么导演分别是谁 Turn 1/5 LLM Assistant Message | content, tool_callsTrue Tool call detected → nameduckduckgo_search, id019b17e045acef53358fa8ae588ace97, raw_args{query: 2025年12月13日 国内票房最高的三部动画片 导演, max_results: 5} Tool arguments parsed successfully. Executing tool duckduckgo_search with args{query: 2025年12月13日 国内票房最高的三部动画片 导演, max_results: 5} Tool output: Title: 中国内地最高电影票房收入列表 - 维基百科自由... Link: https://zh.wikipedia.org/zh-hans/中国内地最高电影票房收入列表 Snippet: 2 days ago - 下列为电影作品在中国内地电影院上映的票房收入相关列表。票房收入以人民币为单位不考虑通货膨胀因素仅以当时售价计量。 ... 下表罗列了2015年《捉妖记》成为中国内地电影总票房冠军之前的华语电影总票房记录... Title: 哪吒之魔童闹海 - 维基百科自由的百科全书 Link: https://zh.wikipedia.org/zh-hans/哪吒之魔童闹海 Snippet: 2 weeks ago - 社会人士方面游戏科学创办人冯骥对本片予以推荐称本片的故事和技术达到全球顶尖水准足以称为“国产动画片天花板”。影评人周黎明认为本片依托经典神话的创新改编精准触达年轻群体其成功源于文化共鸣而非单纯政策激励。《环球时报》前总编辑胡锡进则将本片视为中国动画工业化里程碑称“中国人仰望《功夫熊猫》那些好莱坞动画片并啧啧称奇的时代结束了”。导演陶海认为本片重视剧本创作但仍有提升空间表示“‘发狠’的人物动机以及‘硬拔’式的情节推动是剧作大忌”。漫画家郭竞雄肯定了该片在技术上的成功但批评其带有“粉红战狼思维”和“抖音化认知”。 Title: 影片总票房排行榜 Link: https://piaofang.maoyan.com/rankings/year Snippet: 全部 · 2025年 · 2024年 · 2023年 · 2022年 · 2021年 · 2020年 · 2019年 · 2018年 · 2017年 Title: 全球动画电影票房榜 Link: https://piaofang.maoyan.com/i/globalBox/realtimeRank/anime Snippet: 全球动画电影票房榜 · 2025-12-08 13:26:19 更新 · 影片排名 · 含预售总票房单位元 · 哪吒之魔童闹海 · 2025-1-29 中国大陆首映 · 159.49亿 · 中国(含港澳台) · 海外 · 155.05亿 Title: 2025年动画电影为何能够“三连爆”-中新网 Link: https://www.chinanews.com.cn/cul/2025/12-02/10525112.shtml Snippet: 电影市场迎来了“动画大年”。2025年的年初、年中、年末《哪吒之魔童闹海》(以下简称《哪吒2》)、《浪浪山小妖怪》(以下简称《小妖怪》)、《疯狂动物城2》(以下简称《动物城2》)三部动画电影破圈。 · 《哪吒2》以154.46亿元的票房成为中国影史票房榜冠军、全球影史动画票房榜冠军同时位列2025年全球影史票房榜第五。《小妖怪》以17.19亿元的票房成为中国2D动画电影票房冠军。《动物城2》上映6日票房突破20亿元(截至12月1日记者发稿数据)成为中国影史进口动画票房冠军该影片单日吸金突破7亿元多个平台预测《动物城2》在中国的票房有望突破40亿元。 | ⏱️ Cost: 1.217s Injecting tool result into conversation history. Turn 2/5 LLM Assistant Message | content根据截至2025年12月13日的票房数据中国内地票房最高的三部动画片及其导演如下\n\n1. **《哪吒之魔童闹海》简称《哪吒2》** \n - **票房**159.49亿元人民币 \n - **导演**饺子原名杨宇 \n - **备注**该片不仅成为中国影史票房冠军也位列全球影史动画电影票房榜首是2025年全球票房第五的影片。\n\n2. **《浪浪山小妖怪》简称《小妖怪》** \n - **票房**17.19亿元人民币 \n - **导演**李炜 \n - **备注**该片是中国2D动画电影票房的冠军凭借独特的画风与情感共鸣获得广泛好评。\n\n3. **《疯狂动物城2》简称《动物城2》** \n - **票房**预计突破40亿元人民币截至12月13日已超20亿元上映仅6天即突破20亿 \n - **导演**拜伦·霍华德Byron Howard、里奇·摩尔Rich Moore \n - **备注**作为进口动画电影该片成为中国影史进口动画票房冠军单日票房曾突破7亿元。\n\n **说明**以上信息综合自猫眼专业版、维基百科及中新社报道数据截至2025年12月13日其中《动物城2》仍在上映中最终票房可能进一步上升。, tool_callsFalse No tool calls detected. Returning final answer. Final LLM Answer: 根据截至2025年12月13日的票房数据中国内地票房最高的三部动画片及其导演如下 1. **《哪吒之魔童闹海》简称《哪吒2》** - **票房**159.49亿元人民币 - **导演**饺子原名杨宇 - **备注**该片不仅成为中国影史票房冠军也位列全球影史动画电影票房榜首是2025年全球票房第五的影片。 2. **《浪浪山小妖怪》简称《小妖怪》** - **票房**17.19亿元人民币 - **导演**李炜 - **备注**该片是中国2D动画电影票房的冠军凭借独特的画风与情感共鸣获得广泛好评。 3. **《疯狂动物城2》简称《动物城2》** - **票房**预计突破40亿元人民币截至12月13日已超20亿元上映仅6天即突破20亿 - **导演**拜伦·霍华德Byron Howard、里奇·摩尔Rich Moore - **备注**作为进口动画电影该片成为中国影史进口动画票房冠军单日票房曾突破7亿元。 **说明**以上信息综合自猫眼专业版、维基百科及中新社报道数据截至2025年12月13日其中《动物城2》仍在上映中最终票房可能进一步上升。 ⏳ Elapsed: 12.8 s