conversation-analyser
Critical-thinking and analytics for human–AI conversations — a member of the analyser family.
It scores a single conversation on two tiers:
- Analytics (always on, offline): turn/word counts, prompt/response lengths, question ratio, pushback hits, readability, sentiment trajectory, prompt self-similarity, and temporal metrics when timestamps are present.
- Critical thinking (opt-in, needs an LLM): classifies every human turn under a 7-label prompt taxonomy, derives engagement ratios, an engagement band, and a composite 0–100 critical-thinking score with a component breakdown.
The taxonomy reuses the validated NQ/FU/CH/EX/DG/AC/MT scheme from the ISYS6020
marking pipeline (copied and forked). Design: docs/superpowers/specs/2026-05-23-conversation-analyser-design.md.
Install
pip install -e . # core: analytics + CLI + HTTP API
pip install -e '.[embeddings]' # + prompt self-similarity (sentence-transformers)
pip install -e '.[llm]' # + taxonomy/CT tier (anthropic)
pip install -e '.[embeddings,llm,dev]' # everything
export ANTHROPIC_API_KEY=... # required for the critical-thinking tier
CLI
Bare positional path to analyse (human summary by default, --json for machines);
serve subcommand for the HTTP API — same grammar as the rest of the family.
conversation-analyser transcript.txt # human summary, analytics only
conversation-analyser chat.json --json # full JSON to stdout
conversation-analyser chat.json --llm # add the critical-thinking tier
conversation-analyser log.json --idle-gap 45 # split sub-sessions on 45-min gaps
conversation-analyser raw.txt --parse-mode llm-segment --llm
conversation-analyser serve --port 8009 # run the HTTP API
The critical-thinking tier is opt-in (--llm) to avoid surprise API costs;
without it you get the analytics tier only.
HTTP API
conversation-analyser serve --port 8009
curl -F file=@chat.json 'http://127.0.0.1:8009/analyse' # analytics only
curl -F file=@chat.json -F llm=true 'http://127.0.0.1:8009/analyse'
curl http://127.0.0.1:8009/health
GET /health and POST /analyse (multipart file upload, optional llm form
field) — the same /analyse contract auto-analyser routes to.
Python API
from conversation_analyser import ConversationAnalyser
result = ConversationAnalyser().analyse("transcript.txt", llm=True)
print(result.model_dump_json(indent=2))
Input formats
A pluggable adapter registry tries, in order: structured adapters → heuristic speaker markers → optional LLM segmentation → unsegmented fallback.
- role/content message list (OpenAI/Anthropic):
[{"role": "user", "content": "..."}, ...] - AnythingLLM rows:
[{"prompt": "...", "response": "...", "createdAt": ...}, ...] - flat text with speaker markers:
User:/Assistant:/Me:/ChatGPT:/You said:/ChatGPT said:/Prompt:/Response: - anything else → LLM-segment (needs
[llm]), else a single-blob fallback
.pdf/.docx inputs are text-extracted first (needs pdfplumber/markitdown,
or pre-extract with document-analyser).
Long unstructured transcripts taking the LLM-segment path are split on
paragraph boundaries into chunks (SEGMENT_CHUNK_CHARS, default 36 000) and
classified chunk-by-chunk, so the whole transcript is labelled — not just its
opening — and the band/ratios/score reflect all of it. The number of chunks
(= LLM calls) is guarded by SEGMENT_MAX_CHUNKS (default 12); raise or lift it
per run, e.g. CONVERSATION_ANALYSER_SEGMENT_MAX_CHUNKS=0 for unlimited. A
capped run says so in notes rather than silently dropping the tail.
Cleanly-labelled transcripts take the heuristic path and are never chunked.
The taxonomy
| Code | Meaning |
|---|---|
NQ |
New Query — opens a new topic |
FU |
Follow-up — clarification/elaboration |
CH |
Challenge — pushes back, tests, asks why |
EX |
Extension — applies/compares/synthesises in a new direction |
DG |
Delegation — task hand-off, no engagement |
AC |
Acknowledgement — thanks/confirmation |
MT |
Meta — about the conversation itself |
critical_thinking = (CH+EX)/turns, delegation = DG/turns, filler = (AC+MT)/turns.
Bands: One-Shot · Delegator · Directed · Iterative · Critical.
Graceful degradation
| Missing | Effect |
|---|---|
ANTHROPIC_API_KEY / [llm] |
taxonomy/critical_thinking null; analytics still produced; note llm_unavailable |
[embeddings] |
prompt_self_similarity null; note embeddings_unavailable |
| timestamps | temporal metrics omitted; no sub-session split; note no timestamps |
Output
ConversationAnalysis → an aggregate (rolled up over all human turns, the
headline) plus one SessionAnalysis per idle-gap sub-session, each with
analytics, taxonomy, critical_thinking, and per-turn turns (label +
rationale + preview). See the design spec §8 for the full schema.
Testing
pytest # fast, deterministic (LLM mocked, no network)
pytest -m slow # includes sentence-transformers model download
pytest -m integration # includes live LLM calls
Release files for conversation-analyser 0.5.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| conversation_analyser-0.5.0.tar.gz | 192.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| conversation_analyser-0.5.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 223.7 kB
Release files / conversation_analyser-0.5.0.tar.gz
| Download URL | conversation_analyser-0.5.0.tar.gz |
|---|---|
| Size | 192.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
bd9db9f0adea743d7f18e5066debc408c5dfd7a25be1c3cbf38eacae362683d9
|
|
BLAKE2b-256 checksum How to use checksums |
52316a023fc79231d6e36d908f61a0653c5a50e114566ed9ae2a74ee1808f37c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.0
|
Release files / conversation_analyser-0.5.0-py3-none-any.whl
| Download URL | conversation_analyser-0.5.0-py3-none-any.whl |
|---|---|
| Size | 31.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
99259d9d0ebacbb59991b575b4c35fb35633e989e0b1f4380de6d2c31be59736
|
|
BLAKE2b-256 checksum How to use checksums |
0a945b45d3f3f6c48db104af6203e7980e9b7e84977fe0507bd415da8a0c665f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.0
|