Traduzione automatica
Questa pagina è stata tradotta automaticamente dall'IA e potrebbe contenere errori. In caso di dubbi, fare riferimento alla versione inglese.
Struttura delle Risposte API e Semantica degli Errori¶
Parte del riferimento API web Perplexity — mappa completa nell'indice API.
1. Elementi essenziali della struttura della risposta (disciplina di parsing)¶
- Dati grezzi conservati negli archivi riusciti:
raw_entries.json(plain) eraw_blocks.json(schematizzato, quando recuperato) sono memorizzati insieme agli artefatti renderizzati; il parsing/rendering può essere rieseguito offline (pplx-export re-render) senza dover recuperare nuovamente i dati. - Estrazione dei campi centralizzata in
sites/perplexity/parsers.py(la deriva dello schema richiede una modifica in un solo punto). - Rilevamento della modalità (
normalize.detect_mode; albero decisionale in export-pipeline.md): il segnale con priorità più alta è il camposearch_modedi qualsiasi voce (mappatura alla fine del §3.9); quando tutti i segnali falliscono, ricaduta — computer = URL/computer/tasks/o metadata.mode=="4" o index mode ∈ {ASI,COMPUTER}; council = esiste un passaggio COUNCIL_RESEARCH; deep-research = esiste un passaggio RESEARCH_ANSWER (basato sul contenuto, non su etichette cinesi); altrimenti search. - L'interfaccia utente di computer collassa tutto — basarsi sempre sulle voci/blocchi API; non usare mai il testo dell'interfaccia utente come confine del contenuto.
- Canale duale del subagente (scoperto il 19-07-2026): prompt in
workflow_payload.objective_chunksschematizzato; passaggi/conclusione inbackground_entriesplain; collegati tramiteworkflow_payload.id(toolu_X). - Gli elementi
WORKFLOW_ITEM_SOURCESspesso contengonotext_payload(testo di estrazione pagina del subagente / tabelle di confronto; 450 occorrenze nell'intera libreria, 408 all'interno di payload nidificati di background) oltre asources_payload.sources(elenco di link); lo stesso contenuto appare sia neltextdella voce plain di background (JSON del passaggio incorporato) sia nel payload nidificato schematizzato — i subagenti ancorati renderizzati tramite il percorso plain preservano già il testo (verifica sull'intera libreria il 22-07-2026: 408/408 presenti, nessuno mancante). related_queries/related_query_items(risolto il 23-07-2026): ogni voce contiene raccomandazioni per la domanda successiva — suggerimenti di follow-up che la piattaforma genera per una risposta completata;related_queriesè un array di testi di raccomandazione,related_query_itemsgli elementi strutturati (uuid/upsell_type, ecc.). Conclusione forense: l'uuid di un elemento non è un uuid di thread (0/988 corrispondenze incrociate con gli uuid di thread della libreria), e i testi di raccomandazione non hanno sovrapposizioni con le query di altri thread — per ora non risolvibile in relazioni inter-thread; l'ipotesi di "uuid di thread pre-allocati (materializzati al clic)" rimane non verificata. I dati sono naturalmente preservati nell'archivioraw_entries.json(presenti in oltre la metà dei thread di una libreria di archivio); nessuna azione di raccolta aggiuntiva necessaria; il grafo delle relazioni non costruisce archi a partire da essi.
2. Semantica degli errori e del controllo del rischio¶
| Sintomo | Significato / gestione |
|---|---|
| 403 (con pagina di sfida cf) | Blocco Cloudflare (impronta TLS / controllo della frequenza) — arretrare; urllib + cookie del browser generalmente non lo attivano |
| 401 / 403 a livello API (nessuna pagina di sfida cf) | Cookie di sessione scaduto/invalido — lo strumento solleva immediatamente l'eccezione, nessun backoff; il batch fallisce rapidamente dopo 3 errori di autenticazione consecutivi (aggiornare il cookie) |
| 429 | Limitazione della frequenza — backoff esponenziale (implementato nello strumento) |
| 5xx (500/502/503/504) | Errori server transitori (504 è comunemente un timeout di Cloudflare) — arretrare e riprovare (implementato nello strumento) |
| ENTRY_EXPIRED | Rimosso dalla piattaforma (~3 mesi) — terminale, non riprovare |
| ENTRY_DELETED | Eliminato dall'utente/remoto (anche HTTP 400, codice diverso) — terminale deleted, non riprovare |
_response_type: VIEW_COLLECTION_NOT_ALLOWED (HTTP 200) |
L'account corrente non può visualizzare lo spazio — riprovare con un account che possa |
error_code: VIEW_THREAD_NOT_ALLOWED (HTTP 403) |
L'account corrente non può visualizzare il thread (testato il 23-07-2026: probing uuid di varianti sorelle; l'oggetto esiste ma non è accessibile, non "inesistente") |
status:"failed" dati vuoti |
Stessa classe (la forma di fallimento di get_collection) |
Disciplina di limitazione della frequenza (anti-ban, requisito esplicito dell'utente): 10–20 secondi casuali tra thread batch, nessuna concorrenza, backoff 429/403, backoff-riprova 5xx; paginazione ≥3s; recupero schematizzato ≥4s; recupero metadati spazio ≥3s. Esportazione thread singolo = 1–2 richieste ≈ aprire la pagina una volta.
2.1 Semantica delle interruzioni — valori osservati (22-07-2026; fonte di verità per la classificazione: parsers.classify_wf_status)¶
Il campo locked_reason: appare in thread_metadata / entries[] / background_entries[]
(sia sul lato plain che schematizzato). Unico valore osservato:
| locked_reason | Significato | Distribuzione osservata |
|---|---|---|
spending_limit_exceeded |
interruzione per limite di spesa (quota esaurita; il flusso di lavoro si ferma al punto di interruzione) | esattamente un thread nell'intera libreria (marcatori sia in raw_entries che in raw_blocks) |
Campo stato del flusso di lavoro (workflow_block.status e workflow_payload.status nidificato condividono lo stesso enum) valori osservati:
| status | Semantica | Annotazione di rendering (COMPLETED non ne ha) |
|---|---|---|
WORKFLOW_COMPLETED |
completamento normale | — |
WORKFLOW_AWAITING_NEXT_STEPS |
in attesa di passaggi successivi; con locked_reason=spending_limit_exceeded è una interruzione per limite di spesa (il contenuto si ferma al punto di interruzione); senza locked_reason, interrotto in attesa di continuazione |
⏸ 限额中断(内容截至中断点) (⏸ limit-interrupted — il contenuto si ferma al punto di interruzione) / ⏸ 中断待续 (⏸ interrotto, in attesa di continuazione) |
WORKFLOW_CANCELED |
annullato (aborto utente/piattaforma) | ⛔ 已取消 (⛔ annullato) |
WORKFLOW_CANCELEDosservato 19 volte (16 principali + 3 nidificati), in 7 thread computer (a5e8f481/cfca382d/f2e5957d/8417b02a/2dc5716d/356f833e/ed3714ff).- Nota: lo stato del payload dell'ancora della voce principale potrebbe essere in ritardo (osservato ancora COMPLETED mentre il background era effettivamente CANCELED) —
lo stato reale di un subagente è
workflow_block.statuslato background. - I task di background interrotti non producono notifica di completamento subagent_result; i payload di background non consumati ricadono nell'appendice del thread (vedere "cascata di attribuzione" in subagents-interruptions.md).
- Risposte vuote in modalità computer (doppiamente verificate a luglio 2026, non recuperabili): in modalità computer, alcuni turni hanno una
risposta vuota semplicemente perché il server non ne ha — un recupero API restituisce dati identici all'archivio, e
l'espansione della barra "N passaggi completati" dell'interfaccia utente attiva zero richieste dati (rendering puramente lato client; l'interfaccia utente e
l'API condividono una fonte), quindi l'API non può recuperarli. Solo un sottoinsieme di tali turni è collegato a
locked_reason=spending_limit_exceeded; gli altri non portano alcun marcatore lato server.
2.2 side_by_side_metadata: segnale di variante di riscrittura della risposta (risolto il 23-07-2026)¶
Percorso del campo: entries[].side_by_side_metadata (risposta /rest/thread/<uuid> plain).
Quando la piattaforma genera più versioni di risposta per la stessa query (esperimento A/B o riscrittura), questa è l'unica
traccia lasciata sulla voce attualmente attiva — il corpo della variante sostituita (testo/passaggi/citazioni) non è nella risposta API del thread (caso reale
b2d2632b: la risposta ha solo 1 voce, 1 FINAL; variante 2 completamente invisibile).
Chiavi e valori osservati (evidenza: b2d2632b raw; scansione dell'intera libreria di 2442 voci):
{
"experiment_role": "override-default-model-class:qwen3_instruct-01f7f",
"sibling_uuid": "00000000-0000-5000-8000-000000000000",
"experiment_override": {"override-default-model-class": "qwen3_instruct"},
"selection_status": "SELECTED",
"execution_log": {}
}
| Chiave | Semantica (osservata/ipotizzata) |
|---|---|
sibling_uuid |
Punta alla variante di risposta sorella della stessa query (un altro identificatore di voce/contesto). 7 thread trovati nell'intera libreria; le analisi online (23-07-2026) confermano un link morto: GET /rest/thread/<sibling_uuid> di entrambi gli account restituiscono 403 VIEW_THREAD_NOT_ALLOWED (non 404/ENTRY_EXPIRED — il server lo riconosce come un oggetto esistente ma non visualizzabile), e l'apertura di /search/<sibling_uuid> nel browser (account proprietario) viene reindirizzata SPA alla home — le varianti sostituite non possono essere recuperate tramite sibling_uuid |
selection_status |
SELECTED = la risposta di questa voce è la versione scelta per la visualizzazione; le istanze del gruppo di controllo sono tutte SELECTION_STATUS_UNSPECIFIED |
experiment_role |
Ruolo dell'esperimento. Il gruppo di controllo porta un prefisso [control] (6 casi nell'intera libreria: [control]default-model-class:gpt41, ecc.); il caso reale non ha prefisso (override-default-model-class:qwen3_instruct-01f7f, cioè il gruppo di trattamento di un esperimento di override del modello) |
experiment_override |
Parametri di override dell'esperimento (ad es. override-default-model-class: qwen3_instruct); osservato solo su istanze del gruppo di trattamento |
execution_log |
Osservato come un oggetto vuoto; semantica sconosciuta |
Criteri di restringimento (distinguere "riscrittura genuina che mantiene entrambe le versioni" da "controllo A/B di routine"):
sibling_uuid non vuoto AND (selection_status non vuoto e non SELECTION_STATUS_UNSPECIFIED,
OR experiment_role senza il prefisso [control]) → solo b2d2632b corrisponde tra le 2442 voci dell'intera libreria
(l'unico caso reale confermato; precisione e richiamo sono entrambi 1 su questa libreria, ma n=1 non può essere estrapolato).
Comportamento dello strumento: parsers.collect_answer_variants estrae le corrispondenze; adapter.get_thread
registra un avviso + scrive thread.json.answer_variants (chiave assente quando nessuna corrispondenza);
re-render --thread-json aggiunge/rimuove sul posto (idempotente). Evidenza temporale: il delta created→updated della voce del caso reale
è 53,66 s (generata alle 17:13, poi riscritta/selezionata), e la riscrittura ha avanzato lastUpdated a livello di thread (una riesportazione incrementale
può attivare un recupero, ma la risposta recuperata contiene ancora solo la risposta attiva; le varianti vecchie non sono recuperabili).
Log di rilevamento e flusso di gestione (23-07-2026, sites/perplexity/variant_log.py):
- Marcatore di log: ogni corrispondenza emette una singola riga WARNING con il marcatore uniforme greppabile
ANSWER_VARIANT_DETECTED, includendo tutti i campi di localizzazione e le indicazioni di gestione, nella forma:ANSWER_VARIANT_DETECTED thread=<full uuid> uuid8=<8 chars> title="…" entry=<entry_uuid> sibling=<sibling_uuid> selection_status=SELECTED experiment_role=… | action: …Il percorso online (adapter.get_thread) produce output su ogni corrispondenza di recupero effettiva; offlinere-renderproduce output solo quando il contenuto registrato viene aggiunto/modificato (le esecuzioni idempotenti non generano spam);batchpassa anche un promemoria del conteggio delle corrispondenze su una riga nel riepilogo finale (senza rompere il formato di riepilogo esistente). - Registro centrale:
<out>/index/answer_variants_log.jsonl(un file tracciato, non sottologs/gitignorato) — un JSON per riga (detected_at / source=online|offline / web_uuid / uuid8 / title / entry_uuid / sibling_uuid / selection_status / experiment_role), deduplicato per (web_uuid, entry_uuid); esportazioni/rendering ripetuti non aggiungono all'infinito; detected_at mantiene l'ora del primo avvistamento. - Azione raccomandata in caso di corrispondenza: i fratelli sono empiricamente link morti (vedere la tabella sopra); la risposta alternativa di solito
non può essere recuperata tramite API — confermare prontamente manualmente se la risposta alternativa è ancora ottenibile (conversazione sulla piattaforma / memoria dell'utente / screenshot); se ottenibile,
registrarla manualmente come file
rewritten_answer_variant.mdnella directory del thread; in caso contrario,thread.json.answer_variants+ il registro jsonl fungono da record tracciabile finale.