# minireact
一个轻量级的 ReAct(Reasoning and Acting)智能体框架,让您轻松构建能够思考、使用工具并采取行动的智能代理。 [1](#0-0)
## ✨ 特性
- **🚀 轻量级设计**:核心功能仅依赖少量库,保持框架简洁高效
- **🔧 灵活工具系统**:自动从函数中提取参数和文档,轻松集成自定义工具
- **🧠 智能轨迹管理**:自动管理推理过程,支持上下文窗口智能截断
- **🌊 流式响应**:支持实时流式输出,提供更好的用户体验
- **🔌 多模型支持**:支持 OpenAI、Ollama、OpenRouter 等多种语言模型提供商
- **💾 智能缓存**:内置预测结果缓存,提升性能并降低 API 成本
- **🛡️ 错误恢复**:完善的错误处理机制,确保系统稳定运行
## 🏗️ 核心架构
minireact 基于模块化架构设计,所有组件都继承自统一的 `Module` 基类: [2](#0-1)
```
minireact/
├── Module # 所有组件的基类
├── ReAct # 核心推理-行动循环
├── Tool # 工具封装和执行
├── Signature # 输入输出规范定义
├── Predict # 语言模型交互
├── LM # 多提供商语言模型接口
└── streamify # 流式响应包装器
```
## 🚀 快速开始
### 安装
```bash
pip install -e .
```
### 基础用法
```python
import minireact as mr
# 定义任务签名
signature = mr.Signature(
{"query": mr.InputField()},
{"answer": mr.OutputField()},
instructions="回答用户的问题"
)
# 定义工具函数
def search_tool(query: str):
"""搜索相关信息"""
return f"搜索到关于 {query} 的相关信息"
def calculator(expression: str):
"""计算数学表达式"""
try:
return str(eval(expression))
except:
return "计算错误"
# 创建 ReAct 智能体
agent = mr.ReAct(signature, tools=[search_tool, calculator])
# 执行任务
result = agent(query="计算 15 * 23 + 45")
print(result.answer)
```
### 流式响应
```python
# 使用流式包装器
streaming_agent = mr.streamify(agent)
async for response in streaming_agent(query="今天天气如何?"):
if isinstance(response, mr.ThoughtResponse):
print(f"💭 思考: {response.thought}")
elif isinstance(response, mr.ToolCallResponse):
print(f"🔧 调用工具: {response.tool_name}")
elif isinstance(response, mr.ObservationResponse):
print(f"👀 观察: {response.observation}")
elif isinstance(response, mr.FinishResponse):
print(f"✅ 完成: {response.outputs}")
```
## 🔧 配置语言模型
### OpenAI
```python
import minireact as mr
# 设置 OpenAI 模型
mr.set_model("gpt-4o-mini")
mr.lm_config.set_api_key("your-openai-api-key")
```
### Ollama(本地部署)
```python
# 设置 Ollama
mr.setup_ollama(model="qwen3:8b", api_base="http://localhost:11434")
```
### OpenRouter
```python
# 设置 OpenRouter
mr.setup_openrouter(api_key="your-openrouter-key", model="qwen/qwq-32b-preview")
```
## 📚 核心组件详解
### ReAct 智能体
ReAct 类实现了推理-行动-观察的核心循环: [3](#0-2)
```python
# 创建智能体时的关键参数
agent = mr.ReAct(
signature=signature, # 任务定义
tools=[tool1, tool2], # 可用工具列表
max_iters=5, # 最大迭代次数
lm=custom_lm # 自定义语言模型
)
```
### 工具系统
工具系统自动处理函数封装和参数验证: [4](#0-3)
```python
# 函数会自动转换为 Tool 对象
def my_tool(param1: str, param2: int = 10):
"""工具描述"""
return f"处理 {param1} 和 {param2}"
# 或者手动创建 Tool
tool = mr.Tool(
func=my_function,
name="custom_name",
desc="自定义描述"
)
```
### 签名系统
签名定义了任务的输入输出规范: [5](#0-4)
```python
signature = mr.Signature(
input_fields={"question": mr.InputField()},
output_fields={"answer": mr.OutputField()},
instructions="根据问题提供准确答案"
)
```
## 🔄 执行流程
1. **输入验证**:根据签名验证输入参数
2. **推理循环**:执行思考-行动-观察循环
3. **工具调用**:选择并执行合适的工具
4. **轨迹管理**:记录完整的推理过程
5. **结果提取**:从轨迹中提取最终答案
6. **错误处理**:处理各种异常情况 [6](#0-5)
## 🛠️ 高级功能
### 轨迹截断
当上下文窗口超出限制时,系统会智能截断轨迹: [7](#0-6)
### 预测缓存
内置缓存系统提升性能: [8](#0-7)
### 错误恢复
完善的错误处理和重试机制: [9](#0-8)
## 📁 项目结构
```
mini-react/
├── minireact/
│ ├── __init__.py # 包初始化和导出
│ ├── module.py # 模块基类
│ ├── react.py # ReAct 核心实现
│ ├── tool.py # 工具系统
│ ├── signature.py # 签名系统
│ ├── predict.py # 预测模块
│ ├── lm.py # 语言模型接口
│ ├── streamify.py # 流式响应
│ └── prompt.py # 提示模板
├── examples/ # 使用示例
├── setup.py # 安装配置
└── README.md # 项目说明
```
## 🤝 贡献
欢迎提交 Issue 和 Pull Request 来改进这个项目!
## 📄 许可证
MIT License
---
**minireact** - 让智能体开发变得简单而强大 🚀
## Notes
这个 README 基于项目的实际代码结构和功能编写,突出了 minireact 框架的核心特性:轻量级设计、模块化架构、流式响应支持和多语言模型集成。 [10](#0-9) 相比原有的 README,新版本更加结构化,增加了更多实用的代码示例和配置说明,同时保持了中文文档的特色。
Raw data
{
"_id": null,
"home_page": "https://github.com/cottagephilosopher/mini-react",
"name": "mini-react",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.11",
"maintainer_email": null,
"keywords": null,
"author": "alex",
"author_email": "thisgame@foxmail.com",
"download_url": null,
"platform": null,
"description": "\n# minireact\n\n\u4e00\u4e2a\u8f7b\u91cf\u7ea7\u7684 ReAct\uff08Reasoning and Acting\uff09\u667a\u80fd\u4f53\u6846\u67b6\uff0c\u8ba9\u60a8\u8f7b\u677e\u6784\u5efa\u80fd\u591f\u601d\u8003\u3001\u4f7f\u7528\u5de5\u5177\u5e76\u91c7\u53d6\u884c\u52a8\u7684\u667a\u80fd\u4ee3\u7406\u3002 [1](#0-0) \n\n## \u2728 \u7279\u6027\n\n- **\ud83d\ude80 \u8f7b\u91cf\u7ea7\u8bbe\u8ba1**\uff1a\u6838\u5fc3\u529f\u80fd\u4ec5\u4f9d\u8d56\u5c11\u91cf\u5e93\uff0c\u4fdd\u6301\u6846\u67b6\u7b80\u6d01\u9ad8\u6548\n- **\ud83d\udd27 \u7075\u6d3b\u5de5\u5177\u7cfb\u7edf**\uff1a\u81ea\u52a8\u4ece\u51fd\u6570\u4e2d\u63d0\u53d6\u53c2\u6570\u548c\u6587\u6863\uff0c\u8f7b\u677e\u96c6\u6210\u81ea\u5b9a\u4e49\u5de5\u5177\n- **\ud83e\udde0 \u667a\u80fd\u8f68\u8ff9\u7ba1\u7406**\uff1a\u81ea\u52a8\u7ba1\u7406\u63a8\u7406\u8fc7\u7a0b\uff0c\u652f\u6301\u4e0a\u4e0b\u6587\u7a97\u53e3\u667a\u80fd\u622a\u65ad\n- **\ud83c\udf0a \u6d41\u5f0f\u54cd\u5e94**\uff1a\u652f\u6301\u5b9e\u65f6\u6d41\u5f0f\u8f93\u51fa\uff0c\u63d0\u4f9b\u66f4\u597d\u7684\u7528\u6237\u4f53\u9a8c\n- **\ud83d\udd0c \u591a\u6a21\u578b\u652f\u6301**\uff1a\u652f\u6301 OpenAI\u3001Ollama\u3001OpenRouter \u7b49\u591a\u79cd\u8bed\u8a00\u6a21\u578b\u63d0\u4f9b\u5546\n- **\ud83d\udcbe \u667a\u80fd\u7f13\u5b58**\uff1a\u5185\u7f6e\u9884\u6d4b\u7ed3\u679c\u7f13\u5b58\uff0c\u63d0\u5347\u6027\u80fd\u5e76\u964d\u4f4e API \u6210\u672c\n- **\ud83d\udee1\ufe0f \u9519\u8bef\u6062\u590d**\uff1a\u5b8c\u5584\u7684\u9519\u8bef\u5904\u7406\u673a\u5236\uff0c\u786e\u4fdd\u7cfb\u7edf\u7a33\u5b9a\u8fd0\u884c\n\n## \ud83c\udfd7\ufe0f \u6838\u5fc3\u67b6\u6784\n\nminireact \u57fa\u4e8e\u6a21\u5757\u5316\u67b6\u6784\u8bbe\u8ba1\uff0c\u6240\u6709\u7ec4\u4ef6\u90fd\u7ee7\u627f\u81ea\u7edf\u4e00\u7684 `Module` \u57fa\u7c7b\uff1a [2](#0-1) \n\n```\nminireact/\n\u251c\u2500\u2500 Module # \u6240\u6709\u7ec4\u4ef6\u7684\u57fa\u7c7b\n\u251c\u2500\u2500 ReAct # \u6838\u5fc3\u63a8\u7406-\u884c\u52a8\u5faa\u73af\n\u251c\u2500\u2500 Tool # \u5de5\u5177\u5c01\u88c5\u548c\u6267\u884c\n\u251c\u2500\u2500 Signature # \u8f93\u5165\u8f93\u51fa\u89c4\u8303\u5b9a\u4e49\n\u251c\u2500\u2500 Predict # \u8bed\u8a00\u6a21\u578b\u4ea4\u4e92\n\u251c\u2500\u2500 LM # \u591a\u63d0\u4f9b\u5546\u8bed\u8a00\u6a21\u578b\u63a5\u53e3\n\u2514\u2500\u2500 streamify # \u6d41\u5f0f\u54cd\u5e94\u5305\u88c5\u5668\n```\n\n## \ud83d\ude80 \u5feb\u901f\u5f00\u59cb\n\n### \u5b89\u88c5\n\n```bash\npip install -e .\n```\n\n### \u57fa\u7840\u7528\u6cd5\n\n```python\nimport minireact as mr\n\n# \u5b9a\u4e49\u4efb\u52a1\u7b7e\u540d\nsignature = mr.Signature(\n {\"query\": mr.InputField()},\n {\"answer\": mr.OutputField()},\n instructions=\"\u56de\u7b54\u7528\u6237\u7684\u95ee\u9898\"\n)\n\n# \u5b9a\u4e49\u5de5\u5177\u51fd\u6570\ndef search_tool(query: str):\n \"\"\"\u641c\u7d22\u76f8\u5173\u4fe1\u606f\"\"\"\n return f\"\u641c\u7d22\u5230\u5173\u4e8e {query} \u7684\u76f8\u5173\u4fe1\u606f\"\n\ndef calculator(expression: str):\n \"\"\"\u8ba1\u7b97\u6570\u5b66\u8868\u8fbe\u5f0f\"\"\"\n try:\n return str(eval(expression))\n except:\n return \"\u8ba1\u7b97\u9519\u8bef\"\n\n# \u521b\u5efa ReAct \u667a\u80fd\u4f53\nagent = mr.ReAct(signature, tools=[search_tool, calculator])\n\n# \u6267\u884c\u4efb\u52a1\nresult = agent(query=\"\u8ba1\u7b97 15 * 23 + 45\")\nprint(result.answer)\n```\n\n### \u6d41\u5f0f\u54cd\u5e94\n\n```python\n# \u4f7f\u7528\u6d41\u5f0f\u5305\u88c5\u5668\nstreaming_agent = mr.streamify(agent)\n\nasync for response in streaming_agent(query=\"\u4eca\u5929\u5929\u6c14\u5982\u4f55\uff1f\"):\n if isinstance(response, mr.ThoughtResponse):\n print(f\"\ud83d\udcad \u601d\u8003: {response.thought}\")\n elif isinstance(response, mr.ToolCallResponse):\n print(f\"\ud83d\udd27 \u8c03\u7528\u5de5\u5177: {response.tool_name}\")\n elif isinstance(response, mr.ObservationResponse):\n print(f\"\ud83d\udc40 \u89c2\u5bdf: {response.observation}\")\n elif isinstance(response, mr.FinishResponse):\n print(f\"\u2705 \u5b8c\u6210: {response.outputs}\")\n```\n\n## \ud83d\udd27 \u914d\u7f6e\u8bed\u8a00\u6a21\u578b\n\n### OpenAI\n\n```python\nimport minireact as mr\n\n# \u8bbe\u7f6e OpenAI \u6a21\u578b\nmr.set_model(\"gpt-4o-mini\")\nmr.lm_config.set_api_key(\"your-openai-api-key\")\n```\n\n### Ollama\uff08\u672c\u5730\u90e8\u7f72\uff09\n\n```python\n# \u8bbe\u7f6e Ollama\nmr.setup_ollama(model=\"qwen3:8b\", api_base=\"http://localhost:11434\")\n```\n\n### OpenRouter\n\n```python\n# \u8bbe\u7f6e OpenRouter\nmr.setup_openrouter(api_key=\"your-openrouter-key\", model=\"qwen/qwq-32b-preview\")\n```\n\n## \ud83d\udcda \u6838\u5fc3\u7ec4\u4ef6\u8be6\u89e3\n\n### ReAct \u667a\u80fd\u4f53\n\nReAct \u7c7b\u5b9e\u73b0\u4e86\u63a8\u7406-\u884c\u52a8-\u89c2\u5bdf\u7684\u6838\u5fc3\u5faa\u73af\uff1a [3](#0-2) \n\n```python\n# \u521b\u5efa\u667a\u80fd\u4f53\u65f6\u7684\u5173\u952e\u53c2\u6570\nagent = mr.ReAct(\n signature=signature, # \u4efb\u52a1\u5b9a\u4e49\n tools=[tool1, tool2], # \u53ef\u7528\u5de5\u5177\u5217\u8868\n max_iters=5, # \u6700\u5927\u8fed\u4ee3\u6b21\u6570\n lm=custom_lm # \u81ea\u5b9a\u4e49\u8bed\u8a00\u6a21\u578b\n)\n```\n\n### \u5de5\u5177\u7cfb\u7edf\n\n\u5de5\u5177\u7cfb\u7edf\u81ea\u52a8\u5904\u7406\u51fd\u6570\u5c01\u88c5\u548c\u53c2\u6570\u9a8c\u8bc1\uff1a [4](#0-3) \n\n```python\n# \u51fd\u6570\u4f1a\u81ea\u52a8\u8f6c\u6362\u4e3a Tool \u5bf9\u8c61\ndef my_tool(param1: str, param2: int = 10):\n \"\"\"\u5de5\u5177\u63cf\u8ff0\"\"\"\n return f\"\u5904\u7406 {param1} \u548c {param2}\"\n\n# \u6216\u8005\u624b\u52a8\u521b\u5efa Tool\ntool = mr.Tool(\n func=my_function,\n name=\"custom_name\",\n desc=\"\u81ea\u5b9a\u4e49\u63cf\u8ff0\"\n)\n```\n\n### \u7b7e\u540d\u7cfb\u7edf\n\n\u7b7e\u540d\u5b9a\u4e49\u4e86\u4efb\u52a1\u7684\u8f93\u5165\u8f93\u51fa\u89c4\u8303\uff1a [5](#0-4) \n\n```python\nsignature = mr.Signature(\n input_fields={\"question\": mr.InputField()},\n output_fields={\"answer\": mr.OutputField()},\n instructions=\"\u6839\u636e\u95ee\u9898\u63d0\u4f9b\u51c6\u786e\u7b54\u6848\"\n)\n```\n\n## \ud83d\udd04 \u6267\u884c\u6d41\u7a0b\n\n1. **\u8f93\u5165\u9a8c\u8bc1**\uff1a\u6839\u636e\u7b7e\u540d\u9a8c\u8bc1\u8f93\u5165\u53c2\u6570\n2. **\u63a8\u7406\u5faa\u73af**\uff1a\u6267\u884c\u601d\u8003-\u884c\u52a8-\u89c2\u5bdf\u5faa\u73af\n3. **\u5de5\u5177\u8c03\u7528**\uff1a\u9009\u62e9\u5e76\u6267\u884c\u5408\u9002\u7684\u5de5\u5177\n4. **\u8f68\u8ff9\u7ba1\u7406**\uff1a\u8bb0\u5f55\u5b8c\u6574\u7684\u63a8\u7406\u8fc7\u7a0b\n5. **\u7ed3\u679c\u63d0\u53d6**\uff1a\u4ece\u8f68\u8ff9\u4e2d\u63d0\u53d6\u6700\u7ec8\u7b54\u6848\n6. **\u9519\u8bef\u5904\u7406**\uff1a\u5904\u7406\u5404\u79cd\u5f02\u5e38\u60c5\u51b5 [6](#0-5) \n\n## \ud83d\udee0\ufe0f \u9ad8\u7ea7\u529f\u80fd\n\n### \u8f68\u8ff9\u622a\u65ad\n\n\u5f53\u4e0a\u4e0b\u6587\u7a97\u53e3\u8d85\u51fa\u9650\u5236\u65f6\uff0c\u7cfb\u7edf\u4f1a\u667a\u80fd\u622a\u65ad\u8f68\u8ff9\uff1a [7](#0-6) \n\n### \u9884\u6d4b\u7f13\u5b58\n\n\u5185\u7f6e\u7f13\u5b58\u7cfb\u7edf\u63d0\u5347\u6027\u80fd\uff1a [8](#0-7) \n\n### \u9519\u8bef\u6062\u590d\n\n\u5b8c\u5584\u7684\u9519\u8bef\u5904\u7406\u548c\u91cd\u8bd5\u673a\u5236\uff1a [9](#0-8) \n\n## \ud83d\udcc1 \u9879\u76ee\u7ed3\u6784\n\n```\nmini-react/\n\u251c\u2500\u2500 minireact/\n\u2502 \u251c\u2500\u2500 __init__.py # \u5305\u521d\u59cb\u5316\u548c\u5bfc\u51fa\n\u2502 \u251c\u2500\u2500 module.py # \u6a21\u5757\u57fa\u7c7b\n\u2502 \u251c\u2500\u2500 react.py # ReAct \u6838\u5fc3\u5b9e\u73b0\n\u2502 \u251c\u2500\u2500 tool.py # \u5de5\u5177\u7cfb\u7edf\n\u2502 \u251c\u2500\u2500 signature.py # \u7b7e\u540d\u7cfb\u7edf\n\u2502 \u251c\u2500\u2500 predict.py # \u9884\u6d4b\u6a21\u5757\n\u2502 \u251c\u2500\u2500 lm.py # \u8bed\u8a00\u6a21\u578b\u63a5\u53e3\n\u2502 \u251c\u2500\u2500 streamify.py # \u6d41\u5f0f\u54cd\u5e94\n\u2502 \u2514\u2500\u2500 prompt.py # \u63d0\u793a\u6a21\u677f\n\u251c\u2500\u2500 examples/ # \u4f7f\u7528\u793a\u4f8b\n\u251c\u2500\u2500 setup.py # \u5b89\u88c5\u914d\u7f6e\n\u2514\u2500\u2500 README.md # \u9879\u76ee\u8bf4\u660e\n```\n\n## \ud83e\udd1d \u8d21\u732e\n\n\u6b22\u8fce\u63d0\u4ea4 Issue \u548c Pull Request \u6765\u6539\u8fdb\u8fd9\u4e2a\u9879\u76ee\uff01\n\n## \ud83d\udcc4 \u8bb8\u53ef\u8bc1\n\nMIT License\n\n---\n\n**minireact** - \u8ba9\u667a\u80fd\u4f53\u5f00\u53d1\u53d8\u5f97\u7b80\u5355\u800c\u5f3a\u5927 \ud83d\ude80\n\n## Notes\n\n\u8fd9\u4e2a README \u57fa\u4e8e\u9879\u76ee\u7684\u5b9e\u9645\u4ee3\u7801\u7ed3\u6784\u548c\u529f\u80fd\u7f16\u5199\uff0c\u7a81\u51fa\u4e86 minireact \u6846\u67b6\u7684\u6838\u5fc3\u7279\u6027\uff1a\u8f7b\u91cf\u7ea7\u8bbe\u8ba1\u3001\u6a21\u5757\u5316\u67b6\u6784\u3001\u6d41\u5f0f\u54cd\u5e94\u652f\u6301\u548c\u591a\u8bed\u8a00\u6a21\u578b\u96c6\u6210\u3002 [10](#0-9) \u76f8\u6bd4\u539f\u6709\u7684 README\uff0c\u65b0\u7248\u672c\u66f4\u52a0\u7ed3\u6784\u5316\uff0c\u589e\u52a0\u4e86\u66f4\u591a\u5b9e\u7528\u7684\u4ee3\u7801\u793a\u4f8b\u548c\u914d\u7f6e\u8bf4\u660e\uff0c\u540c\u65f6\u4fdd\u6301\u4e86\u4e2d\u6587\u6587\u6863\u7684\u7279\u8272\u3002\n\n",
"bugtrack_url": null,
"license": null,
"summary": "\u8f7b\u91cf\u7ea7 ReAct \u667a\u80fd\u4f53\u6846\u67b6\u5b9e\u73b0",
"version": "0.1.1",
"project_urls": {
"Homepage": "https://github.com/cottagephilosopher/mini-react"
},
"split_keywords": [],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "6f14293f712b03f29a8f7b50ddf83425d56b7518ff113c5998def8a3387572e3",
"md5": "4d91000051d7e04f9ebe5c1424457492",
"sha256": "bc9eb92429adc7178c30d9290e6153bce1b13c535c00d50ca4588e38641b8413"
},
"downloads": -1,
"filename": "mini_react-0.1.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "4d91000051d7e04f9ebe5c1424457492",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.11",
"size": 30464,
"upload_time": "2025-07-30T07:46:07",
"upload_time_iso_8601": "2025-07-30T07:46:07.523614Z",
"url": "https://files.pythonhosted.org/packages/6f/14/293f712b03f29a8f7b50ddf83425d56b7518ff113c5998def8a3387572e3/mini_react-0.1.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-07-30 07:46:07",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "cottagephilosopher",
"github_project": "mini-react",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"requirements": [
{
"name": "httpx",
"specs": []
},
{
"name": "loguru",
"specs": []
},
{
"name": "openai",
"specs": []
},
{
"name": "python-dotenv",
"specs": []
}
],
"lcname": "mini-react"
}