# Pallas-Bot keeps five dependency extras that install nothing, on purpose

> A NoneBot based QQ bot whose core trick is learning to repeat what a group says, then feeding that learned style into an LLM. The build files are unusually honest about their edges: PostgreSQL and Redis moved into the main dependencies so five old extras could stay empty, the fast Chinese segmenter is in an extra the container installs and a source checkout does not, and one dependency is pinned to a tarball URL with a hash.

**PallasBot/Pallas-Bot** — 《明日方舟》帕拉斯 Bot！群聊复读机，群友聊什么牛牛就说什么，配合LLM做最懂你的牛牛！

- Repository: https://github.com/PallasBot/Pallas-Bot
- Website: https://pallasbot.github.io/Pallas-Bot-Docs/
- Stars: 475 · Forks: 79
- Language: Python
- License: AGPL-3.0
- Published: 2026-09-10 · Updated: 2026-09-10 · Language: en
- Canonical page: https://hysenlabs.com/projects/pallasbot-pallas-bot

## Five extras exist so old commands stop failing

The dependency block ends with a set of extras that install nothing at all:

- `pg = []`
- `coord-redis = []`
- `shard = []`
- `deploy-shard = []`
- `deploy-shard-pg = []`

The comments say why in a form worth reading literally. The pg extra exists for compatibility with older documentation and scripts, because the driver is already in the main dependencies. The coord-redis extra exists because redis is already there. The deploy-shard-pg extra exists to tolerate old build arguments, with PostgreSQL and Redis both already in the main list.

This is a migration left visible on purpose. An empty extra is not an oversight, it is a tombstone for an install command that someone has in a script or a wiki page. Anyone who deletes one of them will not break the application, they will break a stranger's setup note.

Two other dependency decisions are worth the same attention. The main list carries jieba for Chinese word segmentation, and the perf extra carries jieba-next, the Rust accelerated replacement, so the fast path is opt-in rather than default. And the embedding-local extra carries a warning that is unusual to see in a package manifest: do not run a bare sync with that extra enabled, because it will prune a wrapper installed outside the environment, and use a direct pip install of fastembed instead.

The comments also record a decision about databases. From 4.0 onward the default is PostgreSQL, with a note that MongoDB sites can still use beanie and that installing both is harmless.

## The container installs the fast segmenter and a source checkout does not

The build file defaults to two extras:

```
ARG PALLAS_UV_EXTRAS=perf,pg
```

perf is the extra that carries jieba-next. So the image ships the Rust accelerated segmenter while the documented quick start, which runs a plain sync with no extra, leaves you on the pure Python one. Same version number, same lockfile, different tokenizer throughput.

The same file shows how to point the build at a mirror, which is the kind of detail that usually lives in a wiki and is much better as a comment:

```bash
docker build --build-arg BASE_IMAGE=docker.m.daocloud.io/library/python:3.12-slim -t pallasbot:local .
```

The default base image is python:3.12-slim, and there is a second build argument for the package index, so a network that cannot reach Docker Hub or PyPI can be worked around without editing the file.

Two more build arguments are metadata rather than configuration. PALLAS_BOT_VERSION is passed by continuous integration from a release tag or git describe, and the health endpoint reads that environment variable for the bot version. PALLAS_BOT_COMMIT carries the full commit hash, described as being used to validate WebUI release compatibility in a container that has no Git checkout, which is the only way a container can check whether the console frontend it is running matches the backend.

## One dependency is a tarball URL with a checksum and no mirror

Scanning the main dependency list, one entry looks like a maintenance event frozen into the manifest:

```
"pyncm-async @ https://files.pythonhosted.org/packages/52/14/8892c8bef54293eaf13c3ff95685a097d8a48272ce07b8600138f5c24d3e/pyncm_async-1.8.2.tar.gz#sha256=3ea9914f3fbcd4a76ef1d34a4681cff3733507b54caa9aa79f1d04f0e8cd27a7"
```

That is a direct source distribution URL with a hash fragment instead of a version requirement. The hash is the good part: an sdist fetched by URL can be replaced on the index side, and the checksum prevents it. The cost is that the pin will not benefit from any future release, and a reader has no way to tell from the manifest whether the URL exists because the version was yanked or because the project is distributed that way.

The rest of the list is broad and tells you what the bot actually does. NoneBot2 with the FastAPI extra is the framework, with a OneBot v11 adapter and plugins for Alconna command parsing, APScheduler for jobs, localstore for plugin data and htmlrender for rendering. beanie is the asynchronous MongoDB object mapper, sqlalchemy with the asyncio extra and asyncpg are the PostgreSQL path, redis is there for multi-machine coordination and shard claiming, aiosmtplib is a mail client, pypinyin and jieba handle Chinese text, tenacity is retries, psutil and nvidia-ml-py are system and GPU telemetry, curl-cffi and httpx with socks support are HTTP clients, githubkit talks to GitHub, and pillowmd with mdit-py-emoji renders markdown and emoji.

A GPU metrics library in a chat bot dependency list is the most surprising entry, and it suggests the console's operations panel reports hardware utilisation rather than only bot health.

## Compose pins the project name because a Chinese directory name breaks it

The compose file opens with a field that has nothing to do with services, and the comment explains it better than any documentation would:

```yaml
# 固定项目名：避免工作目录名为中文等时，Compose 推导出的项目名为空而报错「project name must not be empty」
name: pallas-bot
```

Docker Compose derives its project name from the working directory. A directory named in Chinese produces an empty name and the command fails before it starts anything. Pinning the name in the file makes the failure impossible, at the cost of two deployments in different places now sharing a project name.

The service block is small. One service named pallasbot, an image reference that can be overridden through PALLAS_BOT_IMAGE and otherwise points at pallasbot/pallas-bot:latest, restart always, and a single published port, 8088 to 8088, which is the port the web console is served on. The environment block pins the timezone to Asia/Shanghai, sets ENVIRONMENT to prod, points the application module at bot:app, and sets MAX_WORKERS to 1.

Database wiring is decided by environment variables rather than by profiles for the main case. PG_HOST and PG_PORT point at the PostgreSQL service inside the same compose project, with a comment saying to delete or change those two lines for an external database. MONGO_HOST and MONGO_PORT are present at the same time and are documented as ignorable in a PostgreSQL only deployment, and the two documented startup commands show the difference, one plain and one adding a mongo profile to the invocation.

## Mounting the whole resource directory covers the help styles

The volume list contains one warning that saves a debugging session. Mounting everything under the resource directory is called out explicitly as wrong, because it hides the image's built-in help styling, so only the voices subdirectory is mounted for voice persistence. Everything else in that tree stays as the image shipped it.

The rest of the mounts follow the same rule of mounting as little as possible. The main configuration file is mounted by name from the host into the container path, and the data directory is mounted wholesale because it holds the protocol instances, the console configuration file and the console password. Site-specific plugins get their own mount from a local plugins directory.

That data directory is where the configuration split becomes visible. The environment example file says to copy it to a .env for NoneBot and pip plugin environment variables only, and that the main configuration belongs in a TOML file while plugin settings belong in the console's own JSON configuration under the data volume. So there are three configuration surfaces, and the file tells you not to duplicate keys between the last two.

The last mount is commented out and worth reading before anyone enables it. The Docker socket is described as approximating host root privileges, and the line is only for deployments where the protocol client runs inside the same container. That is the single most security-relevant line in the deployment configuration, and it ships disabled with an explanation.

## The image contains no markdown, so the build writes a README to satisfy the build backend

The build file contains a workaround that explains itself in a comment. Markdown files are excluded by the ignore file, which is reasonable for a build context, but the packaging configuration points at a README, so the build has to produce one:

```dockerfile
# .dockerignore 排除了 *.md；给 hatchling 提供最小 README 以满足 pyproject readme=
RUN printf '%s\n' '# Pallas-Bot' > README.md
```

A one line file with a heading is enough for the backend, and the comment prevents the next person from wondering why the image has a stub README. This is the kind of detail that would otherwise be rediscovered as a broken build every time the ignore file changed.

The rest of the image is deliberately unglamorous. A single layer installs build essentials, optionally installs the Docker command line client controlled by an argument that defaults to on, and installs pip and uv, using an alternative package index when one is provided. Then the package itself is installed into the system environment with the configured extras and no cache.

The compatibility story is also visible in the same file. The comment above the extras argument notes that the official extensions are deliberately not baked into the image, and that they are installed at runtime through the plugin store or a command that installs an extension. So the image is a runtime and the capability set is data.

## The manifest says 4.4.3, the tag says 4.4.3, and the branch is ahead of both

The package metadata declares version 4.4.3, matching the newest tag v4.4.3. The branch, however, was last pushed on 2026-09-27, ten days after that tag on 2026-09-17, so a source install and a tagged install are different code with the same declared version. Since the quick start clones the repository rather than installing from an index, the version you get depends on which of the two you chose and nothing in the output tells you which.

Python is bounded the same way in both places. The requirements line says 3.12 or later and below 3.13, while the quick start lists Python 3.12 or later with no upper bound, so the resolver is the stricter of the two and 3.13 is rejected.

Two entry points are documented and they are not the same. A source run starts the project with a console command, and the compose file sets the application module to bot:app. At the top level there are five similarly named Python modules, which together cover the worker, the hub, the embedding helper, the work helper and the application itself. That layout is consistent with the stated design of background task delivery and multi-worker sharding, where slow work leaves the message path.

Licensing is AGPL-3.0 with the file referenced from the metadata. Given that the bot has an optional community corpus pool that lets separate deployments share short phrases, and a plugin store and a public community site, that license choice is doing real work rather than being an afterthought.

## Conclusion

Pallas-Bot is a mature-feeling bot framework with the documentation to match, and its dependency and container files are a better reference than most hobby projects manage. Three things to check before you deploy it. The version and the branch drift apart, with the manifest at 4.4.3 while the tree moves on. The fast segmenter is only in the container unless you ask for the perf extra yourself, so a source install and a container install are not the same software. And the compose file mounts the Docker socket on request, which the file itself describes as approximating host root access.

## FAQ

### What does Pallas-Bot need to run?

Python 3.12, PostgreSQL and an OneBot v11 protocol client such as NapCat, or a Docker deployment. The quick start clones the repository, installs uv, syncs, copies the example configuration to pallas.toml, and runs uv run pallas, with the console on port 8088.

### Why does Pallas-Bot keep dependency extras with nothing in them?

The pg, coord-redis, shard, deploy-shard and deploy-shard-pg extras are all empty by design, because PostgreSQL and Redis moved into the main dependencies. They remain so that older documentation and scripts naming those extras keep working.

### Which Chinese segmentation library does Pallas-Bot use?

jieba is in the main dependency list and jieba-next, the Rust accelerated version, is in the perf extra. The Dockerfile installs the perf extra by default, so the container and a plain source install do not run the same segmenter.

### Why does the Pallas-Bot compose file set a fixed project name?

Compose derives a project name from the working directory, and a directory named in Chinese yields an empty name, which makes the command fail with a project name must not be empty error. The file pins name: pallas-bot to prevent that.

### How is Pallas-Bot configured?

Main configuration lives in a TOML file copied from the example, the .env file is for NoneBot and pip plugin environment variables only, and plugin settings are stored in the console's own JSON configuration under the data volume, with a note not to duplicate keys between the last two.

### What is the license and version of Pallas-Bot?

AGPL-3.0, with the licence file referenced from the package metadata, and version 4.4.3 in both the metadata and the newest tag. The branch was last pushed on 2026-09-27, after that tag was cut.

## Sources

- [License: AGPL-3.0](https://github.com/PallasBot/Pallas-Bot/blob/main/LICENSE)
- [PallasBot/Pallas-Bot on GitHub](https://github.com/PallasBot/Pallas-Bot)
- [Project website](https://pallasbot.github.io/Pallas-Bot-Docs/)
- [README](https://github.com/PallasBot/Pallas-Bot/blob/main/README.md)
- [Releases](https://github.com/PallasBot/Pallas-Bot/releases)

---

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