Heuristic Yield Websearch - LLM-powered web search assistant
Project description
HYW — Heuristic Yield Websearch
An LLM-powered terminal assistant that searches, cross-validates, then answers.
Why
LLMs have a knowledge cutoff. Ask "what happened today" and they can only guess.
HYW lets the model decide what to search, how many rounds, and how to cross-validate — then gives you the answer. Not a simple "search and paste" — it's a multi-round heuristic search loop.
Features
- Multi-round autonomous search — The model breaks down questions, crafts search queries, and validates results across up to 6 iterations
- XML tag tool calling — No function calling dependency; works with any LLM provider
- Streaming output — Think and display in real-time; search progress visible as it happens
- Pluggable tool backends — Search / page extract / render are selected by capability, not hard-coded per module
- Built-in websearch service — Ships with
ddgs, Jina AI search/page extraction, and non-browser Markdown render - Rich terminal UI — Gradient titles, Markdown rendering, live spinners
- Multi-turn conversation — Context auto-carried; toggle mode with arrow keys
- Any model via LiteLLM — OpenAI / Anthropic / Google / OpenRouter / local models
Quickstart
# Default install: CLI + ddgs + Jina AI + non-browser render
pip install hyw
# Add entari plugin support
pip install "hyw[entari]"
# Interactive mode
hyw
# Single question
hyw -q "What's the latest in tech news?"
The hyw command is available in the default install.
Configuration
Config file: ~/.hyw/config.yml. Use /config in interactive mode to edit directly.
An example based on the multi-model layout lives at config.example.yml.
In interactive mode, ← / → switches models, and ↑ / ↓ toggles multi-turn vs new session.
Legacy single-model fields (model / api_key / api_base) still work.
# Shared defaults for profiles that don't override them
api_key: sk-or-xxx
api_base: https://openrouter.ai/api/v1
# Active model for startup / single-shot mode
active_model: openrouter/google/gemini-3.1-flash-lite-preview
models:
- model: openrouter/google/gemini-3.1-flash-lite-preview
- model: openrouter/moonshotai/kimi-k2.5
- model: cerebras/gpt-oss-120b
api_key: csk-xxx
api_base: https://api.cerebras.ai/v1
# Preferences
language: zh-CN
max_rounds: 6
headless: true
tools:
index:
ddgs:
search: core.search_ddgs:ddgs_search
jina_ai:
search: core.search_jina_ai:jina_ai_search
page_extract: core.search_jina_ai:jina_ai_page_extract
render:
render: core.render_non_browser:render_markdown_non_browser_result
config:
jina_ai:
page_extract:
prefer_free: true
use:
search: ddgs
page_extract: jina_ai
render: render
# Custom system prompt (appended)
system_prompt: ""
How It Works
User Question
│
▼
┌─────────────────────────────────────┐
│ LLM analyzes & decomposes question │
│ Outputs <search>/<wiki> XML tags │
└──────────────┬──────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ Concurrent search (up to 4/round) │
│ DuckDuckGo → Parse → Structured │
└──────────────┬──────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ LLM validates results & decides: │
│ ├─ Insufficient → new queries, go │
│ └─ Sufficient → final answer │
└─────────────────────────────────────┘
Commands
| Command | Description |
|---|---|
/config |
Open config file in editor |
/stats |
Show session statistics |
/exit |
Exit |
← / → |
Switch active model |
↑ / ↓ |
Toggle Multi Turn / New Session mode |
Project Structure
core/
├── config.py # Model config + tool capability registry
├── main.py # Conversation loop, tool calls, LLM interaction
├── cli.py # Rich terminal UI, streaming output
├── __main__.py # python -m core entry point
├── search_ddgs.py # DDGS search provider
├── search_jina_ai.py # Jina AI search + page extract provider
├── render_non_browser.py # WeasyPrint-based markdown render provider
├── web_search.py # WebToolSuite + service runtime
└── render.py # Standalone markdown render service
Requirements
- Python ≥ 3.12
- Default deps:
litellm·pyyaml·loguru·rich·prompt-toolkit·ddgs·httpx·markdown·Pygments·matplotlib·weasyprint·PyMuPDF·Pillow entari:arclet-alconna·arclet-entari
Roadmap
- ...
- ...
- ...
Contributing
Issues and PRs welcome.
License
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file hyw-0.0.1.tar.gz.
File metadata
- Download URL: hyw-0.0.1.tar.gz
- Upload date:
- Size: 320.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
56e29753f6701116a6930dd0efe3473023006e75bfbd5879b247e36d0557ce38
|
|
| MD5 |
1fa4fc95d9fe39e7a37cc9b9a2dc62ec
|
|
| BLAKE2b-256 |
0f7a8c0e81150e3a993ef8ff670beb601cadace5944ec5e0256e3db429729694
|
Provenance
The following attestation bundles were made for hyw-0.0.1.tar.gz:
Publisher:
workflow.yml on kumoSleeping/heuristic_yield_websearch
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hyw-0.0.1.tar.gz -
Subject digest:
56e29753f6701116a6930dd0efe3473023006e75bfbd5879b247e36d0557ce38 - Sigstore transparency entry: 1096079351
- Sigstore integration time:
-
Permalink:
kumoSleeping/heuristic_yield_websearch@f84f7bfaccffa3819ba701f4efe87ff284f30381 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/kumoSleeping
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
workflow.yml@f84f7bfaccffa3819ba701f4efe87ff284f30381 -
Trigger Event:
push
-
Statement type:
File details
Details for the file hyw-0.0.1-py3-none-any.whl.
File metadata
- Download URL: hyw-0.0.1-py3-none-any.whl
- Upload date:
- Size: 63.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
04dc65ab3bae753b9050a3dc4ebb25794d7121ebd0d9b0f8ca39f430b2acdb80
|
|
| MD5 |
46a74de83d30e5c8af6acde9611dca3c
|
|
| BLAKE2b-256 |
08dcf28660ee347c1fa015d65f9845eb1ccb17facb6ddc827c30c4aec51900ea
|
Provenance
The following attestation bundles were made for hyw-0.0.1-py3-none-any.whl:
Publisher:
workflow.yml on kumoSleeping/heuristic_yield_websearch
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hyw-0.0.1-py3-none-any.whl -
Subject digest:
04dc65ab3bae753b9050a3dc4ebb25794d7121ebd0d9b0f8ca39f430b2acdb80 - Sigstore transparency entry: 1096079369
- Sigstore integration time:
-
Permalink:
kumoSleeping/heuristic_yield_websearch@f84f7bfaccffa3819ba701f4efe87ff284f30381 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/kumoSleeping
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
workflow.yml@f84f7bfaccffa3819ba701f4efe87ff284f30381 -
Trigger Event:
push
-
Statement type: