从认知架构到自主智能体:Cogito项目与AI思考系统构建指南
1. 项目概述一个关于“认知”的AI探索最近在GitHub上看到一个挺有意思的项目叫“Phazorknight/Cogito”。光看这个名字就有点哲学味儿——“Cogito”源自笛卡尔那句著名的“我思故我在”Cogito, ergo sum。这让我立刻来了兴趣一个以“思考”命名的开源项目它到底想解决什么问题是又一个通用大语言模型LLM的轮子还是试图在AI的“认知”层面做一些更本质的探索简单来说Cogito项目是一个围绕“认知架构”Cognitive Architecture和“自主智能体”Autonomous Agent构建的实验性框架。它的核心目标不是单纯地追求模型参数量或者刷榜分数而是尝试为AI系统构建一套更接近人类思考方式的“心智”模型。你可以把它想象成在给AI搭建一个“大脑”的操作系统这个系统里定义了感知、记忆、推理、决策、执行等不同模块如何协同工作而不仅仅是训练一个庞大的神经网络来预测下一个词。为什么这件事值得关注因为当前主流的AI应用无论是ChatGPT这样的对话模型还是Midjourney这样的图像生成器本质上都是“刺激-反应”模式。你输入一个提示Prompt它基于海量数据训练出的模式生成一个概率上最合理的输出。这个过程缺乏持续的内部状态、长期的目标导向和基于经验的反思能力。而Cogito这类项目正是在尝试弥补这一鸿沟让AI不仅能“回答”还能“思考”和“计划”甚至具备一定的“自我意识”雏形。这个项目适合谁呢首先是对AI前沿特别是AGI通用人工智能和认知科学交叉领域感兴趣的开发者、研究者。其次是那些不满足于简单调用API希望深入理解并构建更复杂、更自主的AI应用比如游戏NPC、自动化研究助手、复杂的业务流程自动化代理的工程师。最后它也适合任何对“机器如何思考”这个根本性问题抱有好奇心的技术爱好者。即使你不想从头搭建阅读它的设计思想和代码也能极大地拓宽你对AI可能性的认知边界。2. 核心架构与设计哲学拆解2.1 从“反应式”到“主动式”的范式转变要理解Cogito首先要跳出当前以LLM为中心的“提示工程”思维。传统模式下LLM是一个强大的、但被动的“文本处理器”。它的所有行为都依赖于外部输入的提示来激发自身没有持久的目标、记忆或决策循环。Cogito的设计哲学是赋予AI一个持续的、内生的“认知循环”。这个循环通常包含几个关键阶段感知Perception从环境可以是文本界面、API、数据库、传感器数据流中获取信息。评估与整合Evaluation Integration将新信息与已有的内部记忆短期工作记忆、长期经验记忆进行比对、关联和整合更新对当前状态的理解。目标形成与规划Goal Formation Planning基于当前状态和可能存在的顶层目标比如“解决用户问题”、“赢得游戏”生成或调整子目标并制定一系列具体的行动步骤Plan。决策与执行Decision Execution从规划中选择当前最优先或最可行的行动将其转化为对环境的具体操作指令如调用一个工具函数、生成一段回复、点击一个按钮。反思与学习Reflection Learning行动执行后观察结果与预期进行对比。成功或失败的经验会被结构化地存储到长期记忆中用于优化未来的评估、规划和决策。Cogito试图用代码将这个循环实例化。它不是一个单一的模型而是一个协调器将LLM作为强大的模式识别和推理引擎、向量数据库作为长期记忆、工具调用作为执行器以及一套状态管理逻辑有机地组合在一起。2.2 核心模块深度解析根据对项目代码和文档的研究Cogito的架构通常包含以下核心模块这也是理解其如何工作的关键记忆系统Memory System这是认知架构的基石。Cogito的记忆远不止是存储聊天历史那么简单它通常被设计为多层结构工作记忆Working Memory相当于AI当前的“意识焦点”容量有限存放正在处理的即时信息、当前目标和执行计划。它是高速但易失的。短期记忆Short-term Memory保存最近一段时间如最近10轮对话或事件的详细记录用于维持对话或任务的连贯性。通常可以用一个滑动窗口或队列实现。长期记忆Long-term Memory这是知识的仓库。它又可能分为情景记忆Episodic Memory以时间线序列存储具体的经历事件“昨天我帮用户查询了天气”。语义记忆Semantic Memory存储抽象的概念、事实和关系“巴黎是法国的首都”“Python是一种编程语言”。这部分常借助向量数据库实现通过嵌入Embedding将知识转换为向量便于相似性检索。程序性记忆Procedural Memory存储“如何做某事”的技能比如调用某个API的最佳实践、解决某类问题的固定流程模板。实操心得记忆系统的设计是性能与成本的平衡点。将所有信息都塞进LLM的上下文Context是最简单但也是最昂贵token消耗大且低效的方式。合理的分层设计让LLM只专注于处理工作记忆和从长期记忆中检索出的最相关信息是构建可持续运行智能体的关键。认知引擎Cognitive Engine通常是LLM但在这里它扮演的角色更核心。它不仅仅是“文本生成器”而是“思考过程”的模拟器。Cogito会向LLM提供精心设计的提示Prompt这些提示模板定义了思考的步骤。例如一个典型的推理循环提示可能包含当前状态{工作记忆摘要} 可用工具{工具列表} 长期记忆检索结果{相关记忆片段} 请按以下步骤思考 1. 分析当前状况和我的核心目标。 2. 评估上一步行动的结果并判断是否偏离目标。 3. 基于现有信息和记忆规划下一步最佳行动。如果需要使用工具请说明工具名和输入参数。 4. 输出最终决策。通过这种方式强制LLM进行结构化的、逐步的推理而不是直接跳转到答案。目标与规划管理器Goal Planning Manager这个模块负责将抽象的顶层目标如“开发一个网页应用”分解为可执行的子任务树。它可能使用LLM进行任务分解也可能内置一些规划算法如HTN分层任务网络。它会监控任务执行状态在遇到失败或意外情况时动态调整计划。工具执行与感知接口Tool Execution Perception Interface这是智能体与外部世界交互的手和眼睛。它管理着一套工具函数如网络搜索、代码执行、文件读写、调用其他API并能将LLM输出的自然语言指令准确解析为具体的工具调用。同时它也负责将从环境获取的原始数据如API返回的JSON、网页HTML进行预处理和摘要转化为适合存入记忆和供LLM理解的格式。3. 从零开始构建一个简易Cogito式智能体理解了核心思想后我们抛开复杂的框架用最直接的代码来模拟一个Cogito风格的自主智能体。我们将构建一个“自动化研究助手”它能根据一个宽泛的主题自主进行搜索、阅读、总结并生成一份结构化的报告。3.1 环境准备与核心工具选型我们选择Python作为实现语言因为它有最丰富的AI生态。核心依赖如下语言模型使用OpenAI的GPT-4或GPT-3.5-Turbo API。选择它们是因为在推理和遵循复杂指令方面表现稳定。你也可以用开源的Llama 3等模型但需要自建推理服务复杂度更高。记忆存储使用ChromaDB一个轻量级、易嵌入的向量数据库用于存储和检索长期记忆研究资料。搜索引擎使用Serper API或Google Custom Search JSON API。它们提供了结构化的搜索结果比直接解析HTML更可靠。其他工具requests用于网络请求BeautifulSoup用于简单的HTML解析当API返回内容不足时langchain可选可以帮助我们快速组装一些链但为了理解本质我们尽量自己实现核心逻辑。安装命令pip install openai chromadb requests beautifulsoup43.2 实现核心记忆模块我们先实现一个简化的两层记忆系统对话历史短期记忆和知识库长期记忆。import chromadb from chromadb.config import Settings import openai import hashlib class MemorySystem: def __init__(self, persist_directory./chroma_db): # 初始化向量数据库客户端 self.client chromadb.Client(Settings( chroma_db_implduckdbparquet, persist_directorypersist_directory )) # 获取或创建集合类似于表用于存储知识片段 self.knowledge_collection self.client.get_or_create_collection(nameresearch_knowledge) # 短期记忆一个简单的列表保存最近的对话和事件 self.short_term_memory [] self.embedding_model text-embedding-ada-002 # OpenAI的嵌入模型 def _get_embedding(self, text): 获取文本的向量嵌入 response openai.Embedding.create( modelself.embedding_model, inputtext ) return response[data][0][embedding] def add_to_knowledge(self, content, metadataNone): 将一段内容添加到长期记忆知识库 # 生成一个基于内容的唯一ID content_id hashlib.md5(content.encode()).hexdigest()[:16] embedding self._get_embedding(content) self.knowledge_collection.add( embeddings[embedding], documents[content], metadatas[metadata] if metadata else [{}], ids[content_id] ) def query_knowledge(self, query_text, n_results3): 从长期记忆中检索与查询最相关的内容 query_embedding self._get_embedding(query_text) results self.knowledge_collection.query( query_embeddings[query_embedding], n_resultsn_results ) # results 包含 documents, metadatas, distances if results[documents]: return \n---\n.join(results[documents][0]) # 返回拼接的相关知识 return def add_to_short_term(self, event): 添加事件到短期记忆并控制其长度 self.short_term_memory.append(event) # 保持短期记忆只保留最近20条事件 if len(self.short_term_memory) 20: self.short_term_memory.pop(0) def get_short_term_context(self): 获取短期记忆的文本摘要作为上下文 return \n.join([f- {e} for e in self.short_term_memory[-5:]]) # 只取最近5条作为上下文注意事项嵌入生成和向量检索是计算和API调用的开销点。在实际应用中需要考虑缓存策略避免对相同内容重复生成嵌入。另外短期记忆的长度需要根据任务复杂度和LLM的上下文窗口精心设计太长会浪费token太短会丢失重要上下文。3.3 构建认知循环与决策逻辑这是智能体的“大脑”核心。我们设计一个think_and_act函数它模拟一次完整的认知循环。class ResearchAgent: def __init__(self, openai_api_key): openai.api_key openai_api_key self.memory MemorySystem() self.llm_model gpt-4 # 或 gpt-3.5-turbo self.current_goal self.plan [] def think_and_act(self, new_observation): 核心认知循环。 new_observation: 来自环境的新信息如用户指令、工具执行结果。 # 1. 更新短期记忆 self.memory.add_to_short_term(f观察: {new_observation}) # 2. 准备思考的上下文 short_term_ctx self.memory.get_short_term_context() long_term_knowledge self.memory.query_knowledge(new_observation) # 根据新观察检索相关知识 tools_list 1. web_search(query): 使用搜索引擎查询网络信息。\n2. read_webpage(url): 阅读并总结网页内容。\n3. write_report(outline, content): 将内容写入最终报告。 # 3. 构建促使LLM进行结构化思考的提示 system_prompt 你是一个自主研究助手。请基于以下信息进行一步一步的推理然后决定下一步行动。 user_prompt f ## 当前状况 短期记忆最近事件 {short_term_ctx} 相关长期知识 {long_term_knowledge} 当前顶层目标{self.current_goal} 当前计划步骤{self.plan} ## 最新观察 {new_observation} ## 可用工具 {tools_list} 请严格按以下格式思考并输出 分析 分析当前状况、目标进展以及最新观察的含义。 /分析 评估 评估现有计划是否仍然有效是否需要调整。 /评估 规划 如果需要进行下一步规划具体的下一个行动。必须从可用工具中选择一个或输出“任务完成”。如果是工具请指定工具名和完整的输入参数。 示例web_search(query量子计算的最新突破 2024) /规划 决策 最终输出你的决定格式为TOOL: 工具名和参数 或 DECISION: 其他决定 /决策 # 4. 调用LLM进行“思考” response openai.ChatCompletion.create( modelself.llm_model, messages[ {role: system, content: system_prompt}, {role: user, content: user_prompt} ], temperature0.1 # 低温度保证决策的稳定性 ) reasoning_text response.choices[0].message.content print([Agent Reasoning]\n, reasoning_text) # 5. 解析LLM的输出提取决策 decision self._parse_decision(reasoning_text) # 6. 执行决策 result self._execute_decision(decision) # 7. 将本次循环的“思考过程”和“结果”也存入记忆用于后续反思 self.memory.add_to_short_term(f思考: {reasoning_text}) self.memory.add_to_short_term(f行动: {decision}) self.memory.add_to_short_term(f结果: {result}) return decision, result def _parse_decision(self, text): 从LLM的回复中解析出决策部分 import re decision_match re.search(r决策\s*(.*?)\s*/决策, text, re.DOTALL) if decision_match: return decision_match.group(1).strip() # 简单提取最后一行作为决策 lines text.strip().split(\n) for line in reversed(lines): if line.startswith(TOOL:) or line.startswith(DECISION:): return line return DECISION: 无法解析决策请求澄清。 def _execute_decision(self, decision): 根据决策执行具体工具或动作 if decision.startswith(TOOL: web_search): # 解析查询参数 import re match re.search(rquery([^]), decision) if match: query match.group(1) return self.tool_web_search(query) elif decision.startswith(TOOL: read_webpage): match re.search(rurl([^]), decision) if match: url match.group(1) return self.tool_read_webpage(url) elif decision DECISION: 任务完成: print(任务完成) return 任务已标记完成。 else: return f无法执行未知决策: {decision} # 下面是具体的工具实现 def tool_web_search(self, query): print(f[执行搜索] 关键词: {query}) # 这里应调用Serper或Google Search API返回结构化摘要 # 模拟返回 mock_result f搜索{query}的结果摘要...此处包含3条关键信息 # 将搜索结果作为知识存入长期记忆 self.memory.add_to_knowledge(mock_result, metadata{source: web_search, query: query}) return mock_result def tool_read_webpage(self, url): print(f[阅读网页] URL: {url}) # 使用requests和BeautifulSoup获取并摘要网页内容 # 模拟返回 mock_summary f网页{url}的内容摘要... self.memory.add_to_knowledge(mock_summary, metadata{source: webpage, url: url}) return mock_summary def set_goal(self, goal): 设置智能体的初始目标 self.current_goal goal self.memory.add_to_short_term(f目标设定: {goal}) # 初始可以触发一次思考来制定初始计划 initial_obs f我的新目标是{goal}。请开始制定研究计划。 self.think_and_act(initial_obs)3.4 运行你的第一个自主智能体现在让我们启动这个智能体给它一个研究任务。if __name__ __main__: import os # 假设你的OpenAI API Key已设置在环境变量中 agent ResearchAgent(openai_api_keyos.getenv(OPENAI_API_KEY)) # 步骤1设定目标 research_topic 量子计算在药物发现领域的最新应用进展2023-2024年 agent.set_goal(research_topic) # 步骤2启动自主循环这里简化为手动触发几次 # 第一次思考可能会决定先去搜索 decision, result agent.think_and_act(目标已设定准备开始研究。) print(f决策: {decision}) print(f结果: {result}\n) # 假设上一步搜索返回了一些文章链接智能体下一步可能决定阅读其中一篇 # 这里我们模拟一个观察即搜索到了一个相关URL decision2, result2 agent.think_and_act(网络搜索返回了三条相关信息其中一条的URL是https://example.com/quantum-drug-discovery-2024) print(f决策2: {decision2}) print(f结果2: {result2}\n) # 智能体会继续循环直到它认为信息足够并决策“任务完成”开始撰写报告。这个简易的智能体会根据目标、记忆和最新观察自主决定是搜索、阅读还是结束任务。它展示了Cogito项目最核心的“感知-思考-行动”循环。4. 进阶实现目标分解与动态规划上面的例子中规划和目标管理还比较简单。一个更成熟的Cogito式系统需要能处理复杂目标。我们可以引入一个专门的规划模块。class PlanningModule: def __init__(self, llm_model): self.llm_model llm_model def decompose_goal(self, main_goal): 使用LLM将主目标分解为子任务列表 prompt f 请将以下复杂研究目标分解为一个有序的、可执行的子任务列表。每个子任务应该是一个具体的行动。 目标{main_goal} 输出格式为严格的JSON列表 [ {{id: 1, task: 子任务1描述, type: search|read|analyze|write}}, {{id: 2, task: 子任务2描述, type: search|read|analyze|write}}, ... ] response openai.ChatCompletion.create( modelself.llm_model, messages[{role: user, content: prompt}], temperature0 ) import json try: plan json.loads(response.choices[0].message.content) return plan except json.JSONDecodeError: # 如果LLM输出不符合JSON返回一个默认的简单计划 return [{id: 1, task: f搜索关于{main_goal}的信息, type: search}] def update_plan(self, current_plan, last_task_result, current_state): 根据上一个任务的结果和当前状态动态调整计划 # 这是一个简化的逻辑如果上一个任务失败或信息不足可能会插入新的调查任务 if 信息不足 in last_task_result or 失败 in last_task_result: # 请求LLM建议如何调整计划 prompt f 原计划{current_plan} 上一个任务结果{last_task_result} 当前状态{current_state} 由于遇到困难请建议如何调整原计划。输出一个调整后的新计划JSON格式同上。 # ... 调用LLM获取新计划并返回 pass return current_plan然后在ResearchAgent的think_and_act循环中整合这个规划模块。智能体会先检查当前计划self.plan是否为空或已完成如果是则调用decompose_goal。在执行每个子任务后用update_plan来评估并可能调整后续计划。这使得智能体具备了应对挫折和不确定性的能力。5. 常见问题、调试技巧与优化方向在实际构建和运行此类自主智能体时你会遇到一系列典型问题。以下是一些实录的坑和解决方案。5.1 LLM的“幻觉”与决策漂移问题智能体在思考过程中可能会“忘记”核心目标或者规划出完全不相关的行动例如在研究量子计算时突然决定去查天气。LLM也可能在解析自身输出时出错导致决策无法执行。解决方案强化系统提示System Prompt在每次调用LLM的提示中反复、清晰地强调核心目标和行为约束。例如开头固定加上“你是一个专注于完成‘XXX目标’的研究助手任何思考和行为都必须围绕此目标展开。”结构化输出强制像我们上面做的那样使用XML标签分析,决策等强制LLM按格式输出这大大降低了解析难度和幻觉概率。也可以使用OpenAI的JSON Mode功能直接要求返回JSON对象。设置决策验证层在_parse_decision和_execute_decision之间加入一个简单的验证逻辑。例如检查决策中的工具是否在允许列表内查询关键词是否明显偏离主题可以通过计算与主题的嵌入相似度实现。降低Temperature在决策步骤使用较低的temperature如0.1减少随机性使输出更稳定、可预测。5.2 循环失控与成本控制问题智能体可能陷入死循环比如不断搜索同一个关键词或者进行大量无意义的网络调用导致高昂的API费用和运行时间爆炸。解决方案设置循环上限和超时在think_and_act外层设置最大循环次数如50次和总运行时间限制。实现循环检测在短期记忆中记录最近N次行动和观察。在每次决策前检查是否出现了高度相似的行动序列如果是则触发“陷入循环”的异常处理可以强制改变策略或请求人工干预。成本预算管理为每个工具调用尤其是LLM调用和搜索API设置预算。例如记录已消耗的token数和API调用次数当接近阈值时让智能体进入“节俭模式”或直接停止。细化工具设计不要让“搜索”工具过于宽泛。可以设计更具体的工具如search_academic_papers、search_news并在提示中指导LLM在何种情况下使用何种工具。5.3 记忆管理效率低下问题向量数据库检索返回的内容可能不精准或者短期记忆过长导致LLM上下文被无关信息占据影响推理质量。解决方案记忆摘要Summarization不要将完整的原始文本如一整篇文章直接存入记忆或送入上下文。使用LLM对长文本进行摘要只存储和检索核心观点。可以在add_to_knowledge前先调用一次LLM进行摘要。分层检索先根据元数据如来源、时间进行过滤再在缩小范围后进行向量相似度检索提高精度。动态上下文窗口不要总是把全部短期记忆塞给LLM。设计一个算法根据当前任务从短期记忆中筛选出最相关的几条事件。这可以通过计算事件描述与当前查询的嵌入相似度来实现。定期记忆整理实现一个后台进程定期对长期记忆中的相似条目进行去重和合并保持知识库的简洁和高效。5.4 工具执行的可靠性与错误处理问题网络工具调用失败超时、404错误、解析网页内容时遇到反爬虫机制、工具返回的格式不符合预期等。解决方案完善的错误处理与重试在所有工具函数内部实现try-catch对网络错误进行指数退避重试。将工具执行失败的具体原因如“网络超时”、“页面不存在”作为清晰的观察结果返回给智能体让它能据此调整计划。结果规范化工具函数应尽可能返回结构化的、干净的数据而不是原始HTML或杂乱的JSON。例如read_webpage工具应该返回{title: ..., summary: ..., key_points: [..., ...]}。工具能力描述精准化在提供给LLM的工具列表描述中不仅要写工具名还要清晰说明其输入输出格式、可能发生的错误以及适用场景。这能帮助LLM更好地选择和使用工具。构建一个像Cogito这样真正健壮、可用的认知架构系统是一个庞大的工程涉及稳定性、安全性、效率等多方面的挑战。上述的简易实现和问题排查希望能为你打开一扇门理解自主智能体是如何“思考”和“行动”的。真正的价值不在于复现某个框架而在于吸收其思想将其应用到解决实际问题的过程中去。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2579957.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!