parfold
Parallel async primitives for tree-based operations: fold, unfold, map, filter, and sorting.
Why?
When you need to process many items with async functions (like LLM calls), sequential execution is slow. parfold provides tree-structured parallelism that achieves O(log n) depth instead of O(n).
# Sequential: O(n) round trips
result = items[0]
for item in items[1:]:
result = await combine(result, item)
# Parallel fold: O(log n) round trips
from parfold import fold
result = await fold(items, combine)
Installation
pip install parfold
Primitives
fold — parallel tree reduction
Combines a list into a single result using parallel binary tree reduction.
from parfold import fold
async def combine(a: str, b: str) -> str:
# Your async combining logic (e.g., LLM call)
return await summarize_together(a, b)
chunks = ["chunk1", "chunk2", "chunk3", "chunk4"]
summary = await fold(chunks, combine)
How it works: Instead of combining left-to-right, fold pairs items and combines each pair in parallel, then pairs the results, and so on. For 8 items, that's 3 levels of parallelism instead of 7 sequential operations.
unfold — parallel tree expansion
Expands a seed into leaves by recursively decomposing, with all children expanded in parallel.
from parfold import unfold
async def decompose(query: str) -> list[str]:
if is_specific_enough(query):
return [] # Leaf node
return await generate_subqueries(query)
specific_queries = await unfold("broad research question", decompose)
map — parallel transform
Applies an async function to each item in parallel.
from parfold import map
results = await map(items, async_transform)
filter — parallel predicate
Keeps items where the async predicate returns True.
from parfold import filter
relevant = await filter(items, async_is_relevant)
Sorting
Sorting algorithms using async comparison functions:
from parfold import quicksort, mergesort
async def compare(a, b) -> int:
# Return negative if a < b, positive if a > b, 0 if equal
return await llm_compare(a, b)
sorted_items = await quicksort(items, compare)
# or
sorted_items = await mergesort(items, compare)
Quicksort parallelizes comparisons to the pivot within each partition. Mergesort parallelizes the recursive sorting of left/right halves.
BST — Binary Search Tree
Lock-free BST with parallel inserts and O(1) sorted traversal.
from parfold import BST
async def compare(a: str, b: str) -> int:
return await llm_compare(a, b)
tree = BST(compare)
# Parallel inserts
await asyncio.gather(*[tree.insert(x) for x in items])
# O(1) access to sorted order (no comparisons needed)
for item in tree:
print(item)
# O(1) min/max
print(tree.min, tree.max)
Uses optimistic concurrency control for parallel inserts. Maintains a threaded linked list through nodes for cheap traversal.
| Operation | Comparisons | Time |
|---|---|---|
insert() |
O(log n) | O(1) pointer ops |
min/max |
0 | O(1) |
for x in tree |
0 | O(n) |
contains() |
O(log n) | — |
CachedCompare
Wrap your comparison function to cache results:
from parfold import BST, CachedCompare
cached = CachedCompare(llm_compare)
tree = BST(cached)
# After operations:
print(f"Cache: {cached.hits} hits, {cached.misses} misses")
Use Cases
- Summarization: Fold document chunks into a single summary
- Search: Fold chunks while filtering by relevance to a query
- Research expansion: Unfold a broad question into specific searches
- Ranking: Sort items using LLM-based comparison
- Clustering: Fold items into groups using LLM-based merging
Requirements
- Python 3.10+
- No dependencies (just
asyncio)
License
MIT
Metadata
Release files for parfold 0.1.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| parfold-0.1.3.tar.gz | 17.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| parfold-0.1.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 26.7 kB
Release files / parfold-0.1.3.tar.gz
| Download URL | parfold-0.1.3.tar.gz |
|---|---|
| Size | 17.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
81ae645ed44dc83637ca3f2664a5d474b13f35e501e4bbb31cf92278fbc9d039
|
|
BLAKE2b-256 checksum How to use checksums |
ba96815c9fecca1ed584b697510bd989bf3142f8638f0a30e3700e9debfab803
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jan 13, 2026.
Transparency logRelease files / parfold-0.1.3-py3-none-any.whl
| Download URL | parfold-0.1.3-py3-none-any.whl |
|---|---|
| Size | 9.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f07aa1c947c9c906ddac48c8fbe456707f8e8f35a536a7a1e8f438d9ea5610cf
|
|
BLAKE2b-256 checksum How to use checksums |
b56e5cd34c67e442579c011f1175abfd4f54f5f060c7787a48c7bd9cecd3e891
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jan 13, 2026.
Transparency log