# chatgpt-tarot-divination: a FastAPI app that turns a chat model into a divination engine

> This project is a self-hosted web application that puts several Chinese divination systems, including tarot, BaZi, name stroke counting, dream interpretation and Mei Hua, behind a chat model, with streaming output and saved history. It is a well packaged FastAPI and Tauri application that needs your own OpenAI compatible API key, and it inherits every limitation of the model behind it.

**dreamhunter2333/chatgpt-tarot-divination** — AI 算命，占卜，塔罗牌，姓名五格，周公解梦，生辰八字，梅花易数

- Repository: https://github.com/dreamhunter2333/chatgpt-tarot-divination
- Website: https://divination.app.awsl.uk/
- Stars: 972 · Forks: 247
- Language: TypeScript
- License: MIT
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/dreamhunter2333-chatgpt-tarot-divination

## Seven divination systems behind one chat interface

The application is described in one line as an AI fortune telling and divination app built on ChatGPT, supporting several divination methods with streaming output and history management. The feature list names them explicitly: tarot card divination, birth data analysis known as BaZi, name stroke analysis for personality and fate, dream interpretation, name suggestion based on birth data and the five elements, the traditional Mei Hua method, and relationship divination, the last of which is credited to a contributor by name.

The interesting engineering question is not whether tarot works. It is how seven quite different input shapes, from a card draw to a Chinese name to a free text dream, are normalised into something a language model can be asked about, and what the application does with the answers afterwards.

The backend dependency list gives a strong hint about the mechanism. The pinned requirements include openai at 1.60.0, which is the official client and therefore means the model is called over an HTTP API in the standard chat completions shape, and lunar_python at 1.4.8, a library for the Chinese lunisolar calendar, which is what converts a birth date and time into the BaZi pillars and the five elements. So the calendar arithmetic is computed locally and deterministically, and only the interpretation is handed to the model. That is a meaningful distinction, because the structured part of a BaZi reading is not a hallucination risk in the way the prose around it is.

Everything else in the list is standard web application machinery: fastapi 0.115.7 with uvicorn 0.34.0 as the server, pydantic and pydantic-settings for validation and configuration, PyJWT for tokens, httpx and requests for outbound calls, and redis plus cachetools for caching and rate limiting.

## The streaming and history features are the ones users notice

Four characteristics are called out as the distinguishing features, and two of them are engineering rather than divination.

The first is streaming output, described as the AI reading appearing in real time with a typewriter effect. For a text generation app, this is not decoration. A tarot reading is several paragraphs long, and an interface that waits for the whole answer before displaying anything feels broken. Streaming also changes the failure behaviour, because a connection that dies mid-generation leaves the user with partial text rather than an error dialog.

The second is history, and the documentation is specific about its scope: each divination type automatically saves its most recent 10 records. Ten per type, not a general purpose archive. That is a deliberate product decision, and it has consequences. A user who wants to compare readings across weeks cannot, because the older entries are gone. It also means the app is storing the sensitive inputs of every reading, birth dates and names, somewhere in its own storage, on top of whatever the model provider retains.

The other two are the responsive layout, which the documentation says adapts to phone, tablet and desktop, and a dark mode with theme switching. The repository listing supports the mobile claim: there is a frontend directory, a src directory for the backend, a Dockerfile, a docker-compose file, a vercel.json for the serverless path, and both main.py and main-tauri.py with a src-tauri directory, which is the Rust side of a Tauri desktop build.

So the same codebase is meant to be reachable three ways: a web app on a server, a one click Vercel deployment, and a native desktop application for Windows.

## Four deployment paths, and the configuration each one needs

The documentation describes four ways to run this, which is a reasonable amount of choice for an application with both a server and a client half.

The recommended path is a one click Vercel deployment, described as needing no server and being free. The deployment link carries the repository and the environment variable names api_key and api_base, and the documentation explains that after deployment Vercel assigns a domain and you can bind your own. The same path also accepts optional parameters such as model, github_client_id and github_client_secret.

The second path is a Windows EXE installer downloaded from the releases page, with the API base URL and API key entered in the application settings.

The third is Docker, and this is the path that shows the full configuration surface. The compose file in the repository is the best single view of every knob the application has:

```yaml
services:
  chatgpt-tarot-divination:
    image: ghcr.io/dreamhunter2333/chatgpt-tarot-divination:latest
    container_name: chatgpt-tarot-divination
    restart: always
    ports:
      - 8000:8000
    environment:
      - api_key=sk-xxx
      # - api_base=https://api.openai.com/v1 # optional
      # - model=gpt-3.5-turbo # optional
      # - rate_limit=10/minute # optional
      # - user_rate_limit=600/hour # optional
      - github_client_id=xxx
      - github_client_secret=xxx
      - jwt_secret=secret
      - ad_client=ca-pub-xxx
      - ad_slot=123
```

Read the commented lines carefully, because they are the operational settings. There is a global rate limit of 10 per minute and a per user limit of 600 per hour, both optional, and a model override. The api_base is what lets you point the application at any OpenAI compatible endpoint rather than the official one.

The GitHub OAuth pair, the jwt_secret and the two ad variables are also optional, and their presence tells you a story about the intended deployment. A public instance with GitHub sign in, signed tokens and an advertising slot is a shared service with accounts, not a private tool for one household. The Dockerfile confirms the container shape:

```dockerfile
FROM python:3.11-slim

COPY requirements.txt requirements.txt
RUN python -m pip install --no-cache-dir -r requirements.txt
COPY . /app
WORKDIR /app
EXPOSE 8000
ENTRYPOINT [ "uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000" ]
```

Once started, the application is served on port 8000.

## Running from source splits the frontend build from the Python server

The developer path is the one that shows the real shape of the codebase, and it is a two language project. The stated prerequisites are Node.js 16 or newer, Python 3.8 or newer and pnpm, and the steps are documented as separate frontend and backend phases.

Configuration lives in a .env file in the project root, and the documented keys are the API key, the API base URL, the GitHub OAuth pair and the two advertising variables:

```bash
api_key=sk-xxxx
api_base=https://api.openai.com/v1
github_client_id=xxx
github_client_secret=xxx
ad_client=ca-pub-xxx
ad_slot=123
```

The frontend is a separate project under the frontend directory, built with pnpm and then copied over the static assets the server serves:

```bash
cd frontend
pnpm install
pnpm build --emptyOutDir
cd ..
```

```bash
rm -r dist
cp -r frontend/dist/ dist
```

The backend is a standard Python virtual environment install and launch:

```bash
python3 -m venv ./venv
./venv/bin/python3 -m pip install -r requirements.txt
./venv/bin/python3 main.py
```

And the application is then reachable on port 8000 in the browser.

Two observations. First, the remove and copy step for the dist directory is manual, which means the frontend build is not wired into the backend start, so a change to the client requires two commands and a copy. Second, the Dockerfile copies requirements.txt and installs from it but does not build the frontend, which means the image ships whatever dist content was already in the build context. Anyone changing the client and rebuilding the image has to remember to build the frontend first, and the documentation does not spell that out.

## What the model provider actually receives

The privacy question deserves more attention than the documentation gives it, and it is a direct consequence of the architecture rather than a flaw in the code.

Every reading requires an API key, and the application calls an OpenAI compatible endpoint with the user's input. The inputs are unusually sensitive by the standards of web apps. A BaZi reading needs the date and time of birth, which is a permanent identifier for a person. A name analysis needs the name, which in a Chinese naming context can encode birth information in the strokes. A dream interpretation sends free text describing whatever the user dreamt. A relationship divination adds a second person's details.

None of that is unusual for the category of application, and a person who chooses to use a divination app has implicitly accepted that a machine reads their input. But two things follow that the documentation does not address. The first is that the endpoint is configurable through api_base, so anyone deploying this for a group of users can point it at a self-hosted model and keep the data local, which is the single most useful configuration decision in the compose file. The second is that the application saves the last 10 readings per type, so the inputs are also written to the application's own storage, and whether that storage is a local file, a database or something backed by the redis dependency is not described in the documentation.

The rate limit settings matter for the same reason. A default of 10 requests per minute globally, with an optional 600 per hour per user, is what keeps a shared public instance from running up an unbounded bill against someone's API key. Any self hosted deployment should set those before exposing the port.

## The model is the weakest link, and that is not fixable in the app

The honest limitation of this project is that the interesting output is produced by a system nobody here controls.

A tarot reading, a BaZi interpretation or a dream reading is a long piece of persuasive prose assembled by a model that was given a prompt. Change the model, change the api_base endpoint, or change the prompt in a later release, and the same question produces a different answer with the same authority. There is no fixed corpus of meanings behind it and no consistency guarantee between two readings of the same spread, which is precisely the property people expect from a divination system. The BaZi pillar calculation is deterministic, but the interpretation layered on top is not.

There is a second structural limitation, and it is about the shape of the features rather than the model. The documentation marks every feature as complete, and the feature set spans tarot, BaZi, name strokes, dreams, name suggestion, Mei Hua and relationship divination. Each of those needs its own prompt, its own input parsing and its own output shape, and the requirements file shows no templating, no evaluation harness and no test fixtures for the divination logic. The repository listing does include a tests directory, but the dependency list has no testing framework in it, so what those tests cover is worth checking before relying on any specific method working as described.

For a personal deployment where the reading is entertainment and the answer does not drive a decision, this is fine. For an application that presents itself as authoritative on a person's future, the same architecture is a different proposition, and no amount of front end polish changes that.

## Release history and licence

The licence is MIT, stated plainly in the documentation and with a LICENSE file in the repository root. For an application that talks to a paid API on your behalf, the practical question is not only the code licence but the cost model: every reading is a billable API call against the key you configured, and the default of an OpenAI compatible endpoint means the cost lands wherever that key is billed.

The release record is short and somewhat spread out. The most recent tags are v0.4.0 on 2025-02-23, v0.3.11 on 2024-05-15 and v0.3.10 on 2024-04-28. So the last tagged release is from February 2025, while the last push to the repository was on 2026-08-26. The repository is not archived, so work is still landing, but it is landing after the last release rather than in it.

That gap has a practical consequence for anyone deploying from the image. The compose file points at the latest tag of the container image, and if the image is built from the default branch rather than from a tag, then what you run is whatever the branch contained at build time, which may include changes well beyond v0.4.0 that have never been in a release. If you want a reproducible deployment, build from a specific commit or a tag and pin it, and check that the pinned version matches the frontend and backend you expect, since the two halves are versioned together in the repository but shipped as separate artifacts in a Docker build.

The repository also carries an AGENTS.md file, a .flake8 configuration, a .vercelignore and a .dockerignore, which are the marks of a project with a modern development setup and a serverless deployment target alongside the container and desktop builds.

## Conclusion

This project fits a developer who wants a finished, self-hosted divination application with streaming output, saved history and both browser and desktop clients, and who already has an OpenAI compatible endpoint to point it at. It is the wrong choice if you want offline determinism, because the divination text is produced by a model and a different model or a different prompt will give a different reading every time, and it is the wrong choice if you cannot supply an API key, since the application ships none. Before adopting it, check the licence and the terms of the model provider you will point it at, because both the birth date, the name and the dream text you type are sent to that endpoint on every reading, and read the rate limit settings in the compose file before you expose it publicly.

## FAQ

### What is chatgpt-tarot-divination?

It is a self-hosted web and desktop application that offers several divination methods, including tarot, BaZi birth data analysis, name stroke analysis, dream interpretation, name suggestion and Mei Hua, through an OpenAI compatible API, with streaming output and a history of the last 10 records per type.

### How do I deploy chatgpt-tarot-divination with Docker?

Create a docker-compose.yml with the chatgpt-tarot-divination service, the ghcr.io container image, port 8000 mapped to the host, and an api_key in the environment, then run docker-compose up -d and open http://localhost:8000. The api_base, model and rate limit values are optional overrides.

### Can I point chatgpt-tarot-divination at a different model provider?

Yes. The api_base setting sets the API address and defaults to the official OpenAI address, and there is an optional model setting, so any OpenAI compatible endpoint can be used instead. The Docker image and the local .env file both accept these values.

### How do I run chatgpt-tarot-divination from source?

The documented steps need Node.js 16 or newer, Python 3.8 or newer and pnpm. You create a .env file in the project root, build the frontend with pnpm install and pnpm build inside the frontend directory, copy frontend/dist over dist, then create a Python virtual environment, install requirements.txt and run main.py to serve the app on port 8000.

### What licence is chatgpt-tarot-divination released under?

The project is released under the MIT licence, with a LICENSE file in the repository. The recent tags are v0.4.0 from 2025-02-23, v0.3.11 from 2024-05-15 and v0.3.10 from 2024-04-28, and the last push was on 2026-08-26.

## Sources

- [dreamhunter2333/chatgpt-tarot-divination on GitHub](https://github.com/dreamhunter2333/chatgpt-tarot-divination)
- [License: MIT](https://github.com/dreamhunter2333/chatgpt-tarot-divination/blob/main/LICENSE)
- [Project website](https://divination.app.awsl.uk/)
- [README](https://github.com/dreamhunter2333/chatgpt-tarot-divination/blob/main/README.md)
- [Releases](https://github.com/dreamhunter2333/chatgpt-tarot-divination/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/dreamhunter2333-chatgpt-tarot-divination
