Skip to main content

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.

Python License

English · 中文


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

MIT


Built with curiosity and caffeine.

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

hyw-0.0.2.tar.gz (320.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

hyw-0.0.2-py3-none-any.whl (63.5 kB view details)

Uploaded Python 3

File details

Details for the file hyw-0.0.2.tar.gz.

File metadata

  • Download URL: hyw-0.0.2.tar.gz
  • Upload date:
  • Size: 320.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for hyw-0.0.2.tar.gz
Algorithm Hash digest
SHA256 22910a69407ee16ddcd7207d73e2a85fd2266ba359690c6650511c2f2e92cf2a
MD5 54955f1fd40ff418da096e1d24b77613
BLAKE2b-256 e67e10dbf9272c62a91f8e291683470518f35d46575afe2f54cf02d318b70d84

See more details on using hashes here.

Provenance

The following attestation bundles were made for hyw-0.0.2.tar.gz:

Publisher: workflow.yml on kumoSleeping/heuristic_yield_websearch

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file hyw-0.0.2-py3-none-any.whl.

File metadata

  • Download URL: hyw-0.0.2-py3-none-any.whl
  • Upload date:
  • Size: 63.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for hyw-0.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 294c245d62251d431f7f6f02a6fe352e3627b29f501f7f2bab390a8800fef81b
MD5 ea33fe27993a4c8e6dac368ed60b68a2
BLAKE2b-256 d1b92e055730f43e1cef1249c44f9eb3505ab9dd3ffc759ec936020bef3cd65c

See more details on using hashes here.

Provenance

The following attestation bundles were made for hyw-0.0.2-py3-none-any.whl:

Publisher: workflow.yml on kumoSleeping/heuristic_yield_websearch

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page