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.1.tar.gz (320.6 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.1-py3-none-any.whl (63.2 kB view details)

Uploaded Python 3

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

Hashes for hyw-0.0.1.tar.gz
Algorithm Hash digest
SHA256 56e29753f6701116a6930dd0efe3473023006e75bfbd5879b247e36d0557ce38
MD5 1fa4fc95d9fe39e7a37cc9b9a2dc62ec
BLAKE2b-256 0f7a8c0e81150e3a993ef8ff670beb601cadace5944ec5e0256e3db429729694

See more details on using hashes here.

Provenance

The following attestation bundles were made for hyw-0.0.1.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.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

Hashes for hyw-0.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 04dc65ab3bae753b9050a3dc4ebb25794d7121ebd0d9b0f8ca39f430b2acdb80
MD5 46a74de83d30e5c8af6acde9611dca3c
BLAKE2b-256 08dcf28660ee347c1fa015d65f9845eb1ccb17facb6ddc827c30c4aec51900ea

See more details on using hashes here.

Provenance

The following attestation bundles were made for hyw-0.0.1-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