展示HN:OpenSymbolicAI – 具有类型变量的智能体,而不仅仅是上下文填充
嗨,HN,
我们花了一年时间构建AI代理,但一直遇到同样的问题:提示工程(prompt engineering)并不像软件工程那样。它更像是在猜测。
我们创建了OpenSymbolicAI,旨在将代理开发转变为真正的编程。它是一个开源框架(MIT许可证),允许您使用类型化原语、明确的分解和单元测试来构建代理。
主要问题:上下文窗口的滥用
大多数代理框架(如ReAct)迫使您将工具输出重新放入LLM(大型语言模型)的上下文窗口,以决定下一步。
代理搜索数据库。
代理返回50KB的JSON。
您将这50KB的内容粘贴回提示中,只是为了问“我接下来该做什么?”
这既慢又昂贵,还会让模型感到困惑。
解决方案:将数据作为变量
在OpenSymbolicAI中,LLM生成一个操作变量的计划(代码)。实际的重数据(搜索结果、PDF内容、API负载)存储在Python/运行时变量中,直到某个特定原语真正需要读取它时,才会传递给LLM上下文。
可以将其视为代理的引用传递。LLM操作变量句柄(文档),而Python运行时存储实际数据。
示例:RAG代理
与其让LLM基于一堆文本进行幻觉式的计划,不如直接编写逻辑来操作数据容器。
```python
class ResearchAgent(PlanExecute):
@primitive
def retrieve_documents(self, query: str) -> list[Document]:
"""从向量数据库中获取重文档。"""
# 返回保持在Python内存中的重对象
return vector_store.search(query)
@primitive
def synthesize_answer(self, docs: list[Document]) -> str:
"""利用文档生成答案。"""
# 这是唯一一步实际读取文档文本
context = "\n".join([d.text for d in docs])
return llm.generate(context)
@decomposition(intent="Research quantum computing")
def _example_flow(self):
# LLM生成此执行计划。
# 关键是:LLM管理'docs'变量符号,
# 但在规划过程中从未看到其内部的庞大负载。
docs = self.retrieve_documents("当前量子计算的状态")
return self.synthesize_answer(docs)
```
agent = ResearchAgent()
agent.run("研究固态电池的最新进展")
讨论
我们希望听到社区的反馈:
您在提示工程的脆弱性方面遇到了哪些困难?
什么会让您愿意尝试将提示视为代码?
还有哪些领域可以让这种方法大放异彩?
为了使其适用于您的用例,缺少什么才能使其准备好投入生产?
代码故意保持简单的Python,没有魔法,没有框架锁定。如果这种方法引起共鸣,您可以轻松地根据您的具体需求进行调整或与现有代码库集成。
代码库:
核心(Python): [https://github.com/OpenSymbolicAI/core-py](https://github.com/OpenSymbolicAI/core-py)
文档: [https://www.opensymbolic.ai/](https://www.opensymbolic.ai/)
博客(技术深入): [https://www.opensymbolic.ai/blog](https://www.opensymbolic.ai/blog)
查看原文
Hi HN,<p>We've spent the last year building AI agents and kept hitting the same wall: prompt engineering doesn't feel like software engineering. It feels like guessing.<p>We built OpenSymbolicAI to turn agent development into actual programming. It is an open-source framework (MIT) that lets you build agents using typed primitives, explicit decompositions, and unit tests.<p>THE MAIN PROBLEM: CONTEXT WINDOW ABUSE<p>Most agent frameworks (like ReAct) force you to dump tool outputs back into the LLM's context window to decide the next step.<p>Agent searches DB.<p>Agent gets back 50kb of JSON.<p>You paste that 50kb back into the prompt just to ask "What do I do next?"<p>This is slow, expensive, and confuses the model.<p>THE SOLUTION: DATA AS VARIABLES<p>In OpenSymbolicAI, the LLM generates a plan (code) that manipulates variables. The actual heavy data (search results, PDF contents, API payloads) is stored in the Python/runtime variables and is never passed through the LLM context until a specific primitive actually needs to read it.<p>Think of it as pass-by-reference for Agents. The LLM manipulates variable handles (docs), while the Python runtime stores the actual data.<p>EXAMPLE: A RAG AGENT<p>Instead of the LLM hallucinating a plan based on a wall of text, it simply writes the logic to manipulate the data containers.<p>class ResearchAgent(PlanExecute):<p><pre><code> @primitive
def retrieve_documents(self, query: str) -> list[Document]:
"""Fetches heavy documents from vector DB."""
# Returns heavy objects that stay in Python memory
return vector_store.search(query)
@primitive
def synthesize_answer(self, docs: list[Document]) -> str:
"""Consumes documents to generate an answer."""
# This is the ONLY step that actually reads the document text
context = "\n".join([d.text for d in docs])
return llm.generate(context)
@decomposition(intent="Research quantum computing")
def _example_flow(self):
# The LLM generates this execution plan.
# Crucially: The LLM manages the 'docs' variable symbol,
# but never sees the massive payload inside it during planning.
docs = self.retrieve_documents("current state of quantum computing")
return self.synthesize_answer(docs)
</code></pre>
agent = ResearchAgent() agent.run("Research the latest in solid state batteries")<p>DISCUSSION<p>We'd love to hear from the community about:<p>Where have you struggled with prompt engineering brittleness?<p>What would convince you to try treating prompts as code?<p>Are there other domains where this approach would shine?<p>What's missing to make this production-ready for your use case?<p>The code is intentionally simple Python, no magic, no framework lock-in. If the approach resonates, it's easy to adapt to your specific needs or integrate with existing codebases.<p>Repos:<p>Core (Python): <a href="https://github.com/OpenSymbolicAI/core-py" rel="nofollow">https://github.com/OpenSymbolicAI/core-py</a><p>Docs: <a href="https://www.opensymbolic.ai/" rel="nofollow">https://www.opensymbolic.ai/</a><p>Blog (Technical deep dives): <a href="https://www.opensymbolic.ai/blog" rel="nofollow">https://www.opensymbolic.ai/blog</a>