Maschinenübersetzung
Diese Seite wurde automatisch von KI übersetzt und kann Fehler enthalten. Bei Unklarheiten konsultieren Sie die englische Quelle.
Datenmodell und Verzeichnisvertrag¶
1. Datenmodell (core/models.py)¶
Alle rohen JSON-Daten der Site werden von Parsern in diese Dataclasses abgebildet; nachgelagerte Komponenten (Render/Writer/Relations)
verlassen sich nur auf diese Schicht. Conversation._blocks/_plain sind originalgetreue Abbilder der rohen Antworten (repr=False).
classDiagram
class Account {
+str username
+str display_name
+str plan
+folder (property: display_name or username)
}
class Space {
+str uuid / title / slug / emoji
+int n_threads
}
class Conversation {
+str web_uuid (web entryUUID)
+str psc_uuid (platform context_uuid, nullable)
+str url / title / author / export_via
+str mode (default search)
+str last_updated
+int thread_access
+list~Turn~ turns
+list~Citation~ citations (aggregated, deduped by url)
+list~Asset~ assets
+Report report
+dict metadata (thread_metadata verbatim)
+list~dict~ unconsumed_bgs (attribution waterfall ③ appendix)
+list~dict~ answer_variants (answer-rewrite variant registration, offline-operations.md)
+list~SubAgent~ sub_agents (filled by relations offline rebuild, offline-operations.md §15)
+dict _blocks (schematized fidelity; writer persists raw_blocks.json)
+dict _plain (plain fidelity; writer persists raw_entries.json)
+str exported_at
+n_turns (property)
}
class Turn {
+int index (re-numbered after created_us sort)
+str uuid / context_uuid / query / author
+int created_us / updated_us
+list~Step~ steps (parsed from plain text)
+str answer (extract_answer)
+list~Citation~ citations (turn-level dedupe)
+list~SubAgent~ sub_agents
+dict wf_block (schematized workflow block, mounted by adapter)
+list~dict~ stub_wfs (stub-turn-associated background payloads, mounted by parsers)
+dict metadata (report_info / locked_reason / wf_status, filled by parsers)
}
class Step {
+str step_type (INITIAL_QUERY / FINAL / ASI_TOOL_* / RESEARCH_ANSWER / CODE ...)
+dict content
+str timestamp / tool_name / title / icon / step_id
}
class SubAgent {
+str sub_id (workflow_payload.id, toolu_X)
+str headline / prompt (objective_chunks concatenation)
+list~Step~ steps / str answer / list~Citation~ sources
+str status (background-side true workflow status)
+str locked_reason
}
class Citation {
+str name / url / snippet / timestamp
+str category (default web)
+int turn_index
}
class Asset {
+str uuid / asset_type / filename / url
+str version (default v1) / int n_versions / str created_at
+bool final / str downloaded_to
}
class Report {
+str title / file_name / url / content_md
}
class RelationEdge {
+str src_uuid / dst_uuid / kind / evidence
}
Conversation "1" --> "*" Turn
Conversation "1" --> "0..1" Report
Conversation "1" --> "*" Asset
Conversation "1" --> "0..1" Space
Turn "1" --> "*" Step
Turn "1" --> "*" SubAgent
Turn "1" --> "*" Citation
SubAgent "1" --> "*" Step
SubAgent "1" --> "*" Citation
Verantwortlichkeitshinweise (Zeilennummern relativ zu core/models.py):
Turn.wf_block(models.py:127): der schematisierte Workflow-Block von Computer/Council, eingehängt vonparsers.attach_workflow_blocksnach Eintrags-UUID (parsers.py:231-256); Rendering und Antwort-Fallback (_turn_answer, render.py:489) hängen davon ab; Writer ist schreibgeschützt.Turn.stub_wfs(models.py:131): Hintergrund-Payloads, die über das 10-Sekunden-Fenster mit subagent_result-Stub-Turns verknüpft sind (eingehängt von parsers.match_stub_workflows).Turn.metadata(models.py:134): drei Schlüssel —report_info(RESEARCH_ANSWER-Schritt, parsers.py:199-204),locked_reason(parsers.py:205-208),wf_status(parsers.py:256).Conversation.unconsumed_bgs(models.py:165-170): die Datenquelle des dritten Fallbacks im Attributions-Wasserfall,[{wp, locked_reason, updated, bg_uuid}], gerendert als Anhang am Ende von conversation.md.Conversation.answer_variants(models.py:171-177): Registrierung von Antwort-Umschreibungsvarianten (Datenquelle von thread.json.answer_variants);parsers.collect_answer_variants(parsers.py:589) extrahiert ausentries[].side_by_side_metadatamit Eingrenzungskriterien — Erkennungskette in §18.Conversation.sub_agents(models.py:178-182): Liste der Subagentenläufe auf Konversationsebene, befüllt vonadapter.sub_agentsnur während dercmd_relations-Offline-Neuerstellung; die Export-Pipeline füllt dieses Feld nicht nach (Writer rendert mit einer lokalen sub_map; Relations liest hier) — siehe §15.Conversation._blocks/_plain(models.py:183-190): Originaltreue der rohen Antworten;fs_writerspeichert sie wörtlich als raw_*.json (fs_writer.py:257-266);get_report/get_assets/ sub_agentsand offline re-render all read from them.PerplexityAdapter(None)kann mit einem None-Transport konstruiert werden, um reine Datenmontage wiederzuverwenden (rerender_cmd.py:138).- Duale ID:
web_uuid= Web-Eintrags-UUID (Thread-URL);psc_uuid= Plattform-past_session_contexts-UUID, entnommen aus der ersten nicht-leeren Runde voncontext_uuid(adapter.py:99).
2. Schreibgrenzen und Verzeichnisvertrag¶
2.1 Das web_archive-Thread-Archiv (toolgeneriert; Inhaltsdateien nicht von Hand bearbeitet)¶
web_archive/
├── <account display name>/ # author_folder → _safe_folder cleanup
│ │ # (fs_writer.py:40-51; spaces kept, e.g. "Alice Example")
│ ├── <mode>/ # search | deep-research | computer | council | study
│ │ └── <YYYY-MM-DD>_<title-slug>_<uuid8>/ # thread_dir_for (fs_writer.py:58-72)
│ │ ├── thread.json # metadata + interruptions / answer_variants (optional keys) + report_info + psc_uuid
│ │ ├── conversation.md # compact: per-turn Query/Answer + background appendix (render.py:641)
│ │ ├── turns/turn_NNNN.md # full: complete work-process detail (render.py:596)
│ │ ├── sources.json / sources.md # thread-wide citations (deduped by url)
│ │ ├── report.md # deep-research report (exists only when there is one)
│ │ ├── raw_entries.json # plain response fidelity (always present)
│ │ ├── raw_blocks.json # schematized fidelity (absent for search)
│ │ └── assets/
│ │ ├── assets_manifest.json # versioned manifest (uuid/type/version/destination)
│ │ └── files/ # downloaded bodies (resolve_ext decides extensions)
│ └── ...
├── index/ # state and indexes (see 14.2)
├── relations/ # edges.jsonl + graph.md (rebuilt by the relations command)
├── crosscheck/ # cross-validation reports (manual/review artifacts)
└── <account 2>/ ...
2.2 web_archive/index/-Zustandsdateien (toolverwaltet, nicht von Hand bearbeiten)¶
| Datei | Schreiber | Semantik |
|---|---|---|
library_<account>.json |
cmd_index (index_cmd.py) |
Konto-Thread-Index (GraphQL); standardmäßig inkrementell zusammengeführt (--full überschreibt); enthält auch last_full_index_at / incremental_runs_since_full; Eingabe für Batch-/Zeitplan-/Space-Indizes |
batch_state.json |
BatchState (state.py) |
Prüfpunkt: UUID → Status (ok/error/expired/deleted) + lastUpdated; atomare Schreibvorgänge; beschädigte Dateien werden automatisch als .corrupt-<ts> gesichert |
.cookies.json |
CookieCache (common.py:111, 150) |
Cookie-Cache (12h Frische), mit Quelle und Konto-E-Mail; atomarer Schreibvorgang: temporäre Datei mit 0o600 erstellt, dann os.replace (cookies/cache.py:59-67 — Sitzungsanmeldeinformationen nur für den Eigentümer lesbar; innerhalb des Gitignore-Bereichs) |
space_<slug>.json |
cmd_space_index (spaces_cmd.py:106-167) |
Pro-Space-„Alle“-Thread-Liste (inkl. context_uuid-Dual-ID-Zuordnung) |
space_meta.json |
cmd_spaces --fetch-meta (spaces_cmd.py:299-330) |
Space-Eigentümer-/Mitglieder-Cache (wiederverwendet beim Neuerstellen von Indizes, vermeidet erneutes Abrufen) |
credit_usage_<account>.json |
cmd_usage_backfill (usage_backfill_cmd.py:17) |
Pro-Thread-Guthabennutzung (idempotent und fortsetzbar, alle 25 Einträge geleert) |
cron_snippet.txt |
cmd_schedule (scheduler.py:48-78) |
Cron-Aufruf-Snippet (absolute Pfade) |
answer_variants_log.jsonl |
variant_log.append_registry (variant_log.py:76) |
Zentrales Register für Antwort-Umschreibungsvarianten (Deduplizierung nach Thread+Eintrag, idempotent; eine eingecheckte Datei, nicht logs/) — Erkennungskette in §18 |
logs/ |
--log-file (common.py:218-229) |
Vollständige DEBUG-Protokolle (gitignoriert) |
Die benutzerebene config.toml trägt zusätzlich eine maschinenverwaltete [models]-Tabelle
(der Modellkatalog plus last_refreshed), geschrieben von pplx-ask models --refresh und
befüllt von pplx-export init durch einen tomlkit-Rundlauf, der die anderen
Tabellen und Kommentare des Benutzers erhält — Schema in Konfiguration.
Hinweis für Betreuer — festgelegte Protokollkonstanten. Perplexity-Wire-Protokoll-Fakten, die
an den Parser/Renderer gekoppelt sind — die API version, der Ask-Envelope
supported_block_use_cases, supported_features und der Thread-Read
SCHEMATIZED_BLOCK_USE_CASES — sind in
pplx_export/sites/perplexity/platform.py einzeln hinterlegt und müssen im Gleichschritt mit
parsers.py / render.py aktualisiert werden, wenn sich die Plattform-API ändert (manuell festgelegt, niemals
automatisch aktualisiert; ein Test verbietet verstreute Kopien des Versionsliterals). Modell-IDs hingegen
sind entkoppelte serverseitige Daten und leben im aktualisierbaren [models]-Katalog
oben.
2.3 Die spaces/-Index-Ebene (Repository-Stamm, toolgeneriert)¶
cmd_spaces erstellt neu durch Aggregation von index/library_*.json (spaces_cmd.py:259-389):
eine <slug>.md pro Space (Aggregation der teilnehmenden Konten + Eigentümer-/Mitglieder-Kopfzeile +
Thread-Tabelle + Exportort-Rückverweise) plus das spaces.json-Register. Hinweis: Das Ausgabeverzeichnis
ist spaces/ relativ zum CWD (spaces_cmd.py:332) — es folgt nicht --out;
Informationen zu teilnehmenden Konten werden rein lokal aggregiert, während Eigentümer/Mitglieder aus
dem index/space_meta.json-Cache stammen. Nicht von Hand bearbeiten — die nächste Neuerstellung überschreibt.
2.4 Von Hand bearbeitbar vs. toolverwaltet¶
- Von Hand bearbeitbar: das Systementwurfsdokument, die API-Referenz, die Projekt-README und andere
Spezifikationsdokumente sowie die
web_archive/crosscheck/-Überprüfungsberichte (Spezifikationsdokumente und Überprüfungsartefakte). - Toolverwaltet (Inhaltsdateien nicht von Hand bearbeiten): alle Artefakte in
web_archive/-Thread- Verzeichnissen,index/,spaces/,relations/— wenn Änderungen erforderlich sind, ändern Sie das Tool und führen Sie es erneut aus (Render-Korrekturen erfolgen durch erneutes Rendern, Datenkorrekturen durch den entsprechenden Backfill- Befehl), wobei eine einzige Quelle reproduzierbarer Artefakte erhalten bleibt.