docs(sop_memory): remove unnecessary sections and simplify content

- Remove detailed examples and testing sections
- Simplify content for better readability and focus
This commit is contained in:
jinli.yl 2025-09-01 19:56:16 +08:00
parent 24119413d8
commit f954dbf167

View file

@ -95,10 +95,8 @@ Operator explanation:
Encapsulate the built operation flow into a new composite operation class:
```python
from flowllm.op.base_op import BaseOp
class SearchAndReactOp(BaseOp):
class SearchAndReactOp(BaseToolOp):
description = "Search for information and generate a response based on search results"
input_schema = ...
output_schema = ...
@ -116,194 +114,9 @@ class SearchAndReactOp(BaseOp):
react_op.set_output("response", "response")
# Build operation flow graph
self.flow = search_op >> summary_op >> react_op
return search_op >> summary_op >> react_op
async def execute(self, inputs: Dict[str, Any]) -> Dict[str, Any]:
# Execute operation flow
return await self.flow.execute(inputs)
```
### 2.3 Memory Management
Data transfer between operations is accomplished through memory space:
```python
# Memory space is a key-value store
memory = {}
# set_input reads data from memory
op.set_input("param_name", "memory_key") # op.param_name = memory["memory_key"]
# set_output writes data to memory
op.set_output("result_name", "memory_key") # memory["memory_key"] = op.result_name
```
## 3. Example: Building a Search Q&A SOP
Below is a complete example demonstrating how to build a search Q&A SOP:
```python
from flowllm.op.base_op import BaseOp
from flowllm.op.search.tavily_search_op import TavilySearchOp
from flowllm.op.agent.react_v2_op import ReactV2Op
from flowllm.schema.vector_node import ParamAttr
class SearchQAOp(BaseOp):
description = "Search for information and answer questions based on search results"
input_schema = {
"question": ParamAttr(type=str, description="User question")
}
output_schema = {
"answer": ParamAttr(type=str, description="Answer based on search results")
}
def __init__(self):
super().__init__()
# 1. Create atomic operation instances
search_op = TavilySearchOp()
react_op = ReactV2Op()
# 2. Set data flow
search_op.set_input("query", "question") # Get search query from input question
search_op.set_output("results", "search_results") # Store search results in search_results
react_op.set_input("question", "question") # Get question from input question
react_op.set_input("context", "search_results") # Get context from search_results
react_op.set_output("answer", "answer") # Store answer in answer
# 3. Build operation flow graph
self.flow = search_op >> react_op
async def execute(self, inputs: Dict[str, Any]) -> Dict[str, Any]:
return await self.flow.execute(inputs)
```
## 4. Solution Validation
### 4.1 Unit Testing
To verify the correctness of SOPs, we can write unit tests:
```python
import unittest
import asyncio
from flowllm.op.gallery.mock_op import MockOp
from flowllm.schema.vector_node import ParamAttr
class TestSOPMemory(unittest.TestCase):
def test_simple_flow(self):
# Create mock operations
mock1 = MockOp(
description="Mock operation 1",
input_schema={"input1": ParamAttr(type=str)},
output_schema={"output1": ParamAttr(type=str)}
)
mock2 = MockOp(
description="Mock operation 2",
input_schema={"input2": ParamAttr(type=str)},
output_schema={"output2": ParamAttr(type=str)}
)
# Set data flow
mock1.set_output("output1", "intermediate")
mock2.set_input("input2", "intermediate")
# Build flow
flow = mock1 >> mock2
# Execute flow
result = asyncio.run(flow.execute({"input1": "test input"}))
# Verify results
self.assertIn("output2", result)
```
### 4.2 Integration Testing
Validate the effectiveness of SOPs through real-world scenario testing:
```python
async def test_search_qa():
# Create SearchQA operation
search_qa = SearchQAOp()
# Execute operation
result = await search_qa.execute({
"question": "What is the capital of France?"
})
# Print results
print(f"Question: What is the capital of France?")
print(f"Answer: {result['answer']}")
# Run test
if __name__ == "__main__":
asyncio.run(test_search_qa())
```
### 4.3 Performance Benchmarking
Measure SOP performance metrics:
```python
import time
import asyncio
from flowllm.utils.timer import Timer
async def benchmark_sop(sop_op, inputs, num_runs=10):
total_time = 0
results = []
for _ in range(num_runs):
with Timer() as timer:
result = await sop_op.execute(inputs)
total_time += timer.elapsed_time
results.append(result)
avg_time = total_time / num_runs
print(f"Average execution time: {avg_time:.2f}s")
return results, avg_time
# Run benchmark
search_qa = SearchQAOp()
asyncio.run(benchmark_sop(search_qa, {"question": "What is quantum computing?"}))
```
## 5. Best Practices
### 5.1 Operation Design Principles
- **Single Responsibility**: Each atomic operation should focus on a single functionality
- **Clear Interfaces**: Clearly define input and output schemas
- **Composability**: Design operations with combination with other operations in mind
- **Error Handling**: Properly handle exceptional cases
### 5.2 SOP Design Patterns
- **Pipeline Pattern**: `op1 >> op2 >> op3`
- **Branch Pattern**: `op1 >> (op2 | op3) >> op4`
- **Aggregation Pattern**: `(op1 | op2) >> op3`
- **Conditional Pattern**: Choose different operation paths based on conditions
### 5.3 Debugging Tips
- Use logging to record the input and output of each operation
- Create visualization charts for complex SOPs
- Use mock operations for isolated testing
## 6. Conclusion
Through the SOP Memory mechanism, we can flexibly combine atomic operations to build complex LLM application workflows.
This approach not only improves code maintainability and reusability but also makes the implementation of complex tasks
simpler and more standardized.
As more atomic operations are developed and refined, we can build a richer and more powerful SOP library, further
enhancing the development efficiency and quality of LLM applications.
```