# BidMaster Pro reads the tender document, then runs 21 checks over your draft

> A four-stage agent platform for tender work: interpret the bid document, generate the response, check it against 21 compliance rules, then format and export it. The defaults assume a DeepSeek API key, Postgres, Redis, MinIO and a Celery worker are already waiting.

**guangshu100/BidMaster-Pro** — 全流程 智能招投标 Agent：标书生成 · 招投标解读 · 标书检查 · 标书文档ai排版 · 商机发现 一键完成。 21 项合规检查 · 多模型切换 · RAG 知识库 · OCR 抽取。 从招标公告到可交付 docx 文档，全流程 AI 自动化。

- Repository: https://github.com/guangshu100/BidMaster-Pro
- Stars: 350 · Forks: 97
- Language: Python
- License: AGPL-3.0
- Published: 2026-09-17 · Updated: 2026-09-17 · Language: en
- Canonical page: https://hysenlabs.com/projects/guangshu100-bidmaster-pro

## Interpret reads the tender, and the other three stages work from what it pulled out

The pipeline is four stages and the first one does the reading. Interpret parses PDF, DOCX and TXT bid documents, then extracts what the later stages depend on: scoring criteria, qualification requirements, technical parameters, a scoring matrix table, and risk warnings that flag points where a submission could be rejected.

Generate works off that extraction rather than off the raw file. It produces an outline for the response document, writes section content with expansion and rewriting, pulls company material and past cases out of the retrieval index, and generates the accompanying charts. Check then runs over the generated text, and Format turns the result into a deliverable.

A fifth path sits alongside the four stages. MinerU OCR handles scanned material: a scanned PDF or image goes out to OCR and comes back as structured text plus layout, and the result feeds the interpret and check flows again. The platform setting screen holds the mode, key, endpoint, timeout and polling strategy for it in one tab.

What that shape means for adoption is that the stages are chained, not independent tools. You cannot hand Generate a response document without going through Interpret first, and the check stage's findings come from the extraction rather than from the source file.

## The 21 checks split into qualification screening and internal consistency

The check stage is a rule set, and the categories it covers are named: deposit requirements, signature and seal placement, validity periods, consistency across the document, duplicate content rate, and price reasonableness. On top of those sit compliance against the mandatory requirements in the tender, and a qualification pass that verifies company credentials, past performance and personnel.

Two of those deserve a second look. Duplicate content detection exists because reusing text across submissions is itself a scored risk, and price analysis looks at the logic of the quote rather than at the total, which is a judgement the platform makes for you.

The Format stage closes the loop with a format check that compares the output against the expected template item by item and can correct what it finds, plus a revision mode for multi-person review with annotations. Export produces docx, doc and PDF, and the document is explicit that docx is the only intermediate format, so every other output is derived from it.

The gap worth naming: the README names the categories but does not enumerate all 21 rules or say which of them can be corrected automatically versus only flagged. A team with its own review checklist should assume it has to map that checklist onto these categories by hand.

## One docker-compose command brings up five services on fixed ports

The recommended path is the Docker deployment, and it starts with the repository, an environment file and one compose command.

```bash
git clone <repository-url>
cd BidMaster-Pro
cp .env.example .env
docker-compose up -d
```

The environment file is where you put the LLM API key before starting, and it starts as a copy of .env.example.

Once it is up, the platform runs PostgreSQL on 5432, Redis on 6379, MinIO on 9000, the FastAPI server on 8000 and a Celery worker. The API documentation sits at http://localhost:8000/docs and the MinIO console at http://localhost:9001. Fixed ports mean the defaults will collide with anything else already listening on your machine, and the compose file is where you would change them.

The declared requirements behind that stack are Python 3.12 or newer, Node.js 18 or newer, PostgreSQL 16, Redis 7, and Docker with Docker Compose marked as the recommended route. The desktop client is a separate artifact: a React and Electron application under packages/desktop that talks to the FastAPI server over REST.

## Local development runs uvicorn, a Celery worker and Electron as three separate processes

The local route splits the same system into pieces you start yourself. Backend setup first, with only the infrastructure containers running:

```bash
python -m venv venv
source venv/bin/activate
pip install -e .
docker-compose up -d postgres redis minio
cp .env.example .env
alembic upgrade head
```

The database migration runs through alembic before the server starts, which matters because there is no separate seed step in these instructions. Then three processes have to be alive at the same time:

```bash
uvicorn services.main:app --reload --host 0.0.0.0 --port 8000
celery -A services.celery_app worker --loglevel=info
npm run electron:dev
```

The npm command belongs in packages/desktop, where npm install has already run, and it launches the Electron shell rather than a browser. Without the worker, anything queued for background execution has nothing consuming it, and the README does not describe how the three are supervised during development.

The settings that decide which models get called live in the same environment file.

```bash
BMP_LLM_DEFAULT_MODEL=deepseek/deepseek-chat
BMP_LLM_API_KEY=
BMP_LLM_FALLBACK_MODES=ollama/qwen2.5
BMP_EMBEDDING_MODE=api
BMP_MINERU_MODE=cloud
```

## Tender text stops at 32000 characters before the model ever sees it

One environment variable is the sharpest limit in the whole configuration, and it is easy to miss because it is commented in the example file rather than documented in prose. BMP_TENDER_TEXT_MAX_CHARS=32000 caps the tender and bid text handed to the LLM, in order to avoid an overlong context.

A cap that size is comfortable for a single section of a specification and uncomfortable for a full bid document, which is precisely the input this platform exists to read. The truncation is silent in the sense that nothing in the visible documentation says which part is kept or whether the extraction step reports that it cut input.

If your tenders run long, the practical moves are to pre-split documents before upload and to confirm what the interpret stage retained, rather than to assume the whole file reached the model. Treat 32000 characters as a design constraint on document selection, not as a safety margin.

A related limit sits in the same file on a different axis: BMP_PROJECTS_ROOT defaults to ./projects, so wherever generated bid documents land on disk is decided by one directory setting that is easy to leave pointing at a working checkout.

## Defaults point DeepSeek at a blank key and the OCR stage at a SaaS endpoint

A fresh checkout is not runnable without edits, and the edits are visible in the example environment file. The default model is deepseek/deepseek-chat with the API base at https://api.deepseek.com, and BMP_LLM_API_KEY ships empty. BMP_LLM_MAX_RETRIES is 3, and the fallback list defaults to ollama/qwen2.5, so a local model is the configured second attempt.

Provider switching goes through LiteLLM, so the model strings are prefixed names: siliconflow/* for SiliconFlow, gpt-4 and gpt-3.5-turbo for OpenAI, qwen-max and qwen-plus for Qwen, ollama/qwen2.5 and ollama/llama3 for local models. The same switch is available from platform settings.

The OCR stage defaults outward too. BMP_MINERU_MODE is cloud, the endpoint is https://mineru.net/api/v4, the timeout is 180 seconds per request, and polling happens every 5 seconds up to 60 times with model version vlm. Scanned pages and documents therefore leave your network by default. The alternative is the self_hosted mode with your own token and endpoint, configured either in the environment file or from the MinerU OCR tab, which writes back to .env.

Embedding settings follow the same shape and the same gap: the mode defaults to api with model text-embedding-v3 against a DashScope-compatible base URL, and BMP_EMBEDDING_API_KEY is also empty in the example.

## setuptools packages only services* and core*, so skills/ ships undeclared

The packaging configuration is worth reading before you extend it. pyproject.toml names the distribution bidmaster-pro at version 0.1.0, requires Python 3.12 or newer, and tells setuptools to include the services* and core* packages while excluding tests* and docs*.

The repository root carries more than that: core/, db/, docker/, packages/, services/, skills/, templates/, plus alembic.ini, start.py and start.bat. Only services* and core* are declared as packages, so a new module written under skills/ or db/ is not part of the installed distribution the way one under core/ is. Any private extension that needs to ship with an install has to live in a declared package or the packaging config has to change.

The development tooling is conventional: pytest with asyncio_mode set to auto over a tests path, mypy, and ruff configured for Python 3.12 with a 120 character line length.

On status, the licence is AGPL-3.0, which carries source-availability conditions that a network deployment should have reviewed by whoever handles that, and the version has been 0.1.0 since release V0.1.0 on 2026-06-04. The last push to the repository was on 2026-09-03.

## Conclusion

Adopt BidMaster Pro when one document has to travel from a bid notice to a formatted response with an audit trail of the checks applied, and when you can host Postgres, Redis, MinIO and a Celery worker alongside it. Leave it for teams that need more than 32000 characters of a tender document in context, or that cannot send scanned pages to an external OCR service. Check the defaults first: BMP_LLM_API_KEY and BMP_EMBEDDING_API_KEY both ship empty while the configured modes expect an API, and the licence file is AGPL-3.0.

## FAQ

### What does BidMaster Pro need installed before it can start?

The documented requirements are Python 3.12 or newer, Node.js 18 or newer, PostgreSQL 16, Redis 7, and Docker with Docker Compose, which is the recommended deployment route.

### Which LLM providers can BidMaster Pro call?

Support goes through LiteLLM, covering DeepSeek, SiliconFlow, OpenAI, Qwen and local Ollama models, switchable from platform settings. The default model is deepseek/deepseek-chat with ollama/qwen2.5 as the fallback.

### How does BidMaster Pro handle scanned PDF tender documents?

It integrates MinerU for OCR, either the cloud service at https://mineru.net/api/v4 or a self-hosted OpenAPI endpoint, exposing POST /api/mineru/ocr so extracted text can be reused by the interpret and check flows.

### What licence is BidMaster Pro released under?

The project is released under AGPL-3.0, with the licence text stored in the LICENSE file at the root of the repository.

## Sources

- [guangshu100/BidMaster-Pro on GitHub](https://github.com/guangshu100/BidMaster-Pro)
- [Issues](https://github.com/guangshu100/BidMaster-Pro/issues)
- [License: AGPL-3.0](https://github.com/guangshu100/BidMaster-Pro/blob/main/LICENSE)
- [README](https://github.com/guangshu100/BidMaster-Pro/blob/main/README.md)
- [Releases](https://github.com/guangshu100/BidMaster-Pro/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/guangshu100-bidmaster-pro
