Google AI Overviews i AI Mode

Znakowanie wodne tekstu AI za pomocą SynthID: jak działa generowanie i wykrywanie

Praktyczny przewodnik po znakowaniu wodnym tekstu SynthID z przykładami w Pythonie, wynikami wykrywania, wieloma znakami wodnymi, limitami zastępowania i wykrywaniem przy nieznanych kluczach.

10 min czytania 4 pytań z odpowiedziami

Znak wodny tekstu AI to sygnał celowo wprowadzony do wygenerowanego tekstu. Dla wydawcy użyteczne pytanie jest konkretne: czy potrafimy później rozpoznać wynik działania systemu generującego, który kontrolujemy?

SynthID Text odpowiada na to pytanie. Nie rozstrzyga, czy dowolny artykuł napisała AI. Jego detektor sprawdza skonfigurowany wzorzec statystyczny, a nieudany test pozostawia pochodzenie tekstu nierozstrzygnięte. Repozytorium referencyjne SynthID opisuje zarówno generowanie znaku wodnego, jak i jego wykrywanie.

Ten przewodnik przechodzi przez lokalny przykład w Pythonie, a następnie analizuje trudniejsze przypadki: wiele znaków wodnych, przepisywanie z nowym znakiem wodnym oraz sprawdzanie tekstu, gdy oryginalne klucze są nieznane.

Co tak naprawdę zmienia znak wodny w tekście

Model językowy przypisuje prawdopodobieństwa możliwym kolejnym tokenom. Tokeny mogą reprezentować słowa, części słów lub znaki interpunkcyjne. Generatywny znak wodny zmienia sposób wyboru kolejnego tokenu. Wynikające z tego wybory niosą dowód, który detektor może później zmierzyć.

SynthID wykorzystuje proces zwany próbkowaniem turniejowym. Kandydujące tokeny konkurują ze sobą w ramach pseudolosowych funkcji oceniających. O wyniku decyduje ostatni kontekst tokenów oraz klucze znaku wodnego. Powtarzanie wyboru przez kilka warstw faworyzuje tokeny o mierzalnym wzorcu statystycznym. Detektor odtwarza te wyniki na podstawie gotowego tekstu. Nie musi uruchamiać oryginalnego modelu językowego. Zobacz pracę badawczą o SynthID.

1. Przewidź możliwe kolejne tokeny

Model językowy tworzy rozkład prawdopodobieństwa na swoim słowniku.

2. Zastosuj skonfigurowany znak wodny

Funkcje oceniające oparte na kluczach wpływają na wybór tokenów podczas generowania.

3. Opublikuj zwykły tekst

Sygnał statystyczny podróżuje w wybranej sekwencji tokenów.

4. Odtwórz i oceń

Detektor używa zgodnej tokenizacji i pasującej konfiguracji, aby szukać tego sygnału.

Dłuższe fragmenty zazwyczaj dostarczają więcej dowodów. Wysoce przewidywalne dane wyjściowe pozostawiają mniej alternatywnych tokenów dostępnych dla znaku wodnego. Więcej warstw może pomóc, ale praca badawcza opisuje malejące korzyści, gdy warstwy wyczerpują dostępną zmienność w wyborze tokenów.

Znaki wodne statystyczne i ukryte znaki to coś innego

Zanim wybierzesz detektor, ustal, jakiego sygnału zamierzasz szukać.

MetodaCo przenosi sygnał?Co należy przetestować?
SynthID TextStatystyczne wybory tokenów dokonane podczas generowaniaDowód przy pasującej konfiguracji znaku wodnego
Znacznik ukrytych znakówKonkretne znaki wstawione do ciągu tekstowegoSekwencja znaków i jej udokumentowane kodowanie
Metadane dokumentuPola dołączone do dokumentu lub konteneraMetadane, ich pochodzenie i ewentualny podpis
Klasyfikator tekstu pisanego przez AIWzorce wyuczone na przykładowych tekstachGeneralizacja i fałszywe trafienia w docelowej grupie odbiorców

Skaner Unicode nie może zastąpić detektora SynthID. Znalezienie nietypowego znaku również nie dowodzi autorstwa AI. Nasze wprowadzenie do darmowych narzędzi AmICited omawia znaki wodne oparte na znakach i ich ograniczenia. Poniższy eksperyment dotyczy znakowania wodnego statystycznego.

Logo

Gotowy, by monitorować swoją widoczność w AI?

Śledź, jak chatboty AI wspominają Twoją markę w ChatGPT, Perplexity i innych platformach.

Wygeneruj tekst ze znakiem wodnym w Pythonie

Repozytorium Google jest materiałem referencyjnym i wyraźnie odradza używanie swoich podklas modelu w środowisku produkcyjnym. Wskazuje na implementację w Hugging Face Transformers. Materiał referencyjny udostępnia także podejścia detekcyjne oparte na średniej, średniej ważonej i wytrenowanym detektorze bayesowskim. Uwagi o korzystaniu z repozytorium

Poniższy przykład używa Pythona 3.13, Transformers 4.57.1 i PyTorch 2.8.0. To odtwarzalne wersje przykładowe, a nie twierdzenie, że są to najnowsze wydania. Działa na CPU i przy pierwszym użyciu pobiera publiczny model distilbert/distilgpt2. Ten mały model utrzymuje eksperyment w zasięgu; jakość jego pisania nie jest reprezentatywna dla obecnych asystentów.

Utwórz izolowane środowisko:

python3.13 -m venv .venv
source .venv/bin/activate
python -m pip install "transformers==4.57.1" "torch==2.8.0"

Zapisz bloki Pythona z tego przewodnika, po kolei, w pliku watermark_demo.py. Zacznij od generowania:

import torch
from transformers import (
    AutoModelForCausalLM,
    AutoTokenizer,
    SynthIDTextWatermarkingConfig,
    SynthIDTextWatermarkLogitsProcessor,
    set_seed,
)

MODEL_ID = "distilbert/distilgpt2"
tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
model = AutoModelForCausalLM.from_pretrained(
    MODEL_ID, use_safetensors=True
).to("cpu").eval()

# Public demonstration keys. Never use these as a private production mark.
watermark = SynthIDTextWatermarkingConfig(
    keys=[104729 + 7919 * i for i in range(30)],
    ngram_len=5,
    sampling_table_size=65536,
    sampling_table_seed=42,
    context_history_size=1024,
    skip_first_ngram_calls=True,
)

inputs = tokenizer(
    "A community garden can change a neighborhood in several ways. ",
    return_tensors="pt",
)

def generate(config):
    set_seed(17)
    with torch.inference_mode():
        output = model.generate(
            **inputs,
            watermarking_config=config,
            do_sample=True,
            max_new_tokens=384,
            temperature=0.9,
            top_k=50,
            pad_token_id=tokenizer.eos_token_id,
        )
    # Keep the continuation; the supplied prompt was not watermarked.
    return output[:, inputs["input_ids"].shape[1]:]

marked_ids = generate(watermark)
unmarked_ids = generate(None)
print(tokenizer.decode(marked_ids[0], skip_special_tokens=True))

Generowanie musi ujawniać zgodny potok próbkowania. Przekazanie gotowej odpowiedzi z hostowanego API do tej konfiguracji nie może oznaczyć jej wstecznie. Osobny model musiałby wygenerować nową wersję.

W środowisku produkcyjnym utwórz unikalne losowe klucze i zachowaj konfigurację w tajemnicy. Zachowaj wersję tokenizera, wersję modelu, wersję konfiguracji i powiązany detektor. Rotacja kluczy tworzy nową konfigurację; zachowaj starą konfigurację wykrywania, jeśli nadal musisz rozpoznawać starsze dane wyjściowe. Wskazówki Google dotyczące implementacji

Jak wykrywanie znaku wodnego oblicza dowód

Wykrywanie zaczyna się od tokenizacji tekstu kandydującego i odtworzenia wyniku dla każdego kwalifikującego się okna tokenów i każdej warstwy znaku wodnego. W wykorzystywanej tu implementacji te binarne wyniki nazywane są wartościami g. Uśredniamy je po wykluczeniu powtarzających się kontekstów oraz pozycji na tokenie końca sekwencji lub po nim. Pierwsze cztery tokeny kontynuacji same nie tworzą kompletnego okna pięciu tokenów.

Poniższa funkcja korzysta z metod oceniania i maskowania w Transformers. Przyjmuje jedną sekwencję bez dopełnienia naraz i zwraca surową średnią, a nie prawdopodobieństwo autorstwa.

def score_ids(token_ids, config):
    if token_ids.ndim != 2 or token_ids.shape[0] != 1:
        raise ValueError("Pass one unpadded sequence with shape [1, length].")
    if token_ids.shape[1] < config.ngram_len:
        return {"mean_g": None, "usable_windows": 0}

    processor = SynthIDTextWatermarkLogitsProcessor(
        **config.to_dict(), device=torch.device("cpu")
    )
    with torch.inference_mode():
        values = processor.compute_g_values(token_ids).float()
        unique = processor.compute_context_repetition_mask(token_ids)
        before_eos = processor.compute_eos_token_mask(
            token_ids, tokenizer.eos_token_id
        )[:, config.ngram_len - 1:]
        mask = unique & before_eos.bool()
        usable = int(mask.sum().item())
        if usable == 0:
            return {"mean_g": None, "usable_windows": 0}
        # Boolean indexing retains the layer dimension.
        mean_g = float(values[mask].mean().item())
    return {"mean_g": mean_g, "usable_windows": usable}

print("marked:", score_ids(marked_ids, watermark))
print("unmarked:", score_ids(unmarked_ids, watermark))

def score_text(text, config):
    ids = tokenizer(
        text, add_special_tokens=False, return_tensors="pt"
    )["input_ids"]
    return score_ids(ids, config)

published_text = tokenizer.decode(
    marked_ids[0],
    skip_special_tokens=True,
    clean_up_tokenization_spaces=False,
)
print("published text:", score_text(published_text, watermark))
print("empty text:", score_text("", watermark))

Bezpośrednie sprawdzenie identyfikatorów tokenów oddziela generowanie od serializacji tekstu. Drugie sprawdzenie ćwiczy ścieżkę, którą detektor widzi po publikacji. Oceń swój rzeczywisty potok publikowania i wyodrębniania tekstu, ponieważ może on zmienić dane wejściowe.

Wynik 0,60 nie oznacza 60% prawdopodobieństwa, że tekst napisała AI. Ta funkcja nie ma skalibrowanego progu decyzyjnego. Krótki fragment może przypadkowo uzyskać wysoki wynik. Zgłoś wynik nierozstrzygający, gdy dowody są niewystarczające.

Aby uzyskać użyteczny detektor, zbierz reprezentatywny tekst ludzki, dane wyjściowe modelu bez znaku wodnego oraz dane wyjściowe ze znakiem wodnym. Trzymaj dane kalibracyjne oddzielnie od danych do finalnej oceny. Wybierz próg dla akceptowalnego odsetka fałszywych trafień, oceń wskaźniki wykrywalności na próbkach odłożonych, a wyniki rozbij według języka, długości i typu treści. Pojedyncza para oznaczony/nieoznaczony sprawdza tylko, że przykład działa.

Jako wytrenowaną alternatywę Hugging Face udostępnia detektor bayesowski oraz proces trenowania detektora. Detektor wytrenowany dla niepowiązanych kluczy nie jest zamiennikiem Twojego detektora. Losowo zainicjowany punkt kontrolny lub punkt demonstracyjny nie potwierdza dokładności wykrywania.

Czy można wykryć DOWOLNY znak wodny SynthID bez jego kluczy?

Opublikowane podejście do wykrywania wymaga pasującej konfiguracji. Potrzebna jest też zgodna tokenizacja. Sama wiedza, że dostawca używa algorytmu SynthID, nie daje jego konfiguracji, a publiczne repozytorium nie jest detektorem dla danych wyjściowych każdego dostawcy.

Google opisuje detektory prywatne, detektory udostępniane przez API oraz detektory rozpowszechniane publicznie. Dostawca mógłby zaoferować weryfikację bez ujawniania swojej prywatnej konfiguracji. Wykrywanie i weryfikowalność

W naszym własnym systemie możemy sprawdzić rejestr znanych konfiguracji. Dołącz ten przykład, aby porównać poprawne klucze z niepowiązanymi kluczami demonstracyjnymi:

other_settings = watermark.to_dict()
other_settings["keys"] = [key + 1_000_003 for key in watermark.keys]
other_watermark = SynthIDTextWatermarkingConfig(**other_settings)

known_configs = {
    "demo-original-v1": watermark,
    "demo-other-v1": other_watermark,
}
for name, config in known_configs.items():
    print(name, score_text(published_text, config))

Uruchom złożony plik poleceniem python watermark_demo.py. To porównanie daje dowody dla dwóch znanych konfiguracji. Nie potrafi odkryć dowolnego nieznanego klucza i celowo nie oznacza żadnego z wyników jako wykrycia.

Sprawdzanie wielu konfiguracji oznacza również przeprowadzanie wielu testów statystycznych. Jeśli każdy test dopuszcza fałszywe trafienia, zaakceptowanie dowolnego wyniku pozytywnego może zwiększyć ogólny odsetek fałszywych trafień. Skalibruj całą procedurę wyszukiwania. Tam, gdzie pojedyncze testy dają poprawne wartości p, konserwatywną opcją jest podzielenie całkowitego dopuszczalnego odsetka fałszywych trafień przez liczbę testów. Nie stosuj tej arytmetyki bezpośrednio do surowego wyniku mean_g.

Jeśli żadna znana konfiguracja nie pasuje, właściwym wynikiem jest „Nie wykryto obsługiwanego znaku wodnego”. Możliwości nadal obejmują pisanie przez człowieka, dane wyjściowe AI bez znaku wodnego, nieznany znak wodny oraz edytowany fragment, którego sygnał jest zbyt słaby.

Czy ten sam tekst może nieść wiele znaków wodnych SynthID?

Rozważamy dwa różne rozwiązania.

Wiele warstw w jednej konfiguracji

SynthID już obsługuje listę kluczy. W przykładzie 30 kluczy tworzy 30 warstw w ramach jednego skonfigurowanego znaku wodnego. Detektor łączy ich dowody. Te klucze nie reprezentują automatycznie 30 osobno przypisywalnych autorów lub organizacji. Konfiguracja znaku wodnego

Niezależnie wykrywalne oznaczenia platformy i klienta

Załóżmy, że chcesz, aby detektor obejmujący całą platformę oraz osobny detektor dla konkretnego klienta rozpoznawały ten sam fragment. Przydzielenie grup warstw do tych celów jest opcją projektową eksperymentalną, a nie udokumentowaną gwarancją biblioteki.

Samo połączenie dwóch list kluczy nie dowodzi, że oba oryginalne detektory nadal działają. Każdy detektor wymagałby oceny na połączonym procesie generowania, w tym pod kątem swojej pozycji w sekwencji warstw. Zmierz wskaźnik wykrywalności każdego oznaczenia, trafienia krzyżowe względem innych klientów oraz zachowanie po edycjach. To propozycja inżynieryjna wymagająca eksperymentów, a nie twierdzenie, że SynthID zapewnia niezależne przypisanie wielu właścicieli od razu.

Jeśli usługa centralna musi jedynie zidentyfikować klienta, prostszym rozwiązaniem jest jedna konfiguracja na klienta z wewnętrznym rejestrem. To rozwiązanie nadal wymaga kalibracji w całym rejestrze. Nie zapewnia osobnego oznaczenia obejmującego całą platformę, które można sprawdzić bez przeszukiwania konfiguracji klientów.

Czy można zastąpić istniejący znak wodny?

SynthID nie przechowuje w tekście pola takiego jak watermark_id. Nie ma wartości metadanej, którą można nadpisać. Oryginalny sygnał jest rozproszony w wyborach tokenów.

Jeśli przepiszesz fragment przy użyciu drugiego generatora ze znakiem wodnym, nowy proces generowania wprowadza własny sygnał. Wpływ na wcześniejszy sygnał zależy od wynikowej sekwencji tokenów. Google podaje, że łagodne edycje mogą zachować wykrywalność, natomiast dokładne przepisanie lub tłumaczenie może znacznie obniżyć pewność. Udokumentowane ograniczenia transformacji

Wynika z tego, że drugi znak wodny nie gwarantuje usunięcia pierwszego. Oba sygnały mogą pozostać wykrywalne albo jeden lub oba mogą spaść poniżej swoich progów wykrywania. To wnioskowanie o połączonym procesie pracy; przywołana dokumentacja nie ustala wskaźnika przetrwania dla każdej pary znaków wodnych.

Nieznana pierwsza konfiguracja tworzy praktyczne ograniczenie. Nasz własny detektor może ocenić nasze oznaczenie, ale nie może ustalić, że oryginalne oznaczenie zniknęło. Wymaga to dostępu do oryginalnego pasującego detektora. Nawet wynik negatywny oznacza, że detektor nie znalazł wystarczających dowodów przy swoich ustawieniach, a nie dowód, że usunięto każdy ślad.

Jak testować nakładające się znaki wodne

Zanim stwierdzisz, że oznaczenia współistnieją albo że jedno zastępuje drugie, użyj macierzy testowej. Poniższe pozycje opisują eksperymenty do przeprowadzenia, a nie zmierzone wyniki.

Grupa próbekDetektor ADetektor BCo sprawdza porównanie
Tekst ludzki i tekst AI bez znaku wodnegoUruchomUruchomBazowy poziom fałszywych trafień
Tekst wygenerowany tylko z AUruchomUruchomWykrycie A i przypadkowe trafienia B
Tekst wygenerowany tylko z BUruchomUruchomWykrycie B i przypadkowe trafienia A
Tekst wygenerowany z eksperymentalną konfiguracją połączonąUruchomUruchomCzy każde zamierzone oznaczenie jest wykrywalne
Tekst przepisany pod BUruchomUruchomPrzetrwanie A i wykrycie B po przepisaniu
Krótkie wyjątki i edytowane wersje każdej grupyUruchomUruchomWrażliwość na potok publikowania

Używaj odłożonych promptów i podawaj użyteczne długości tekstu, liczebność próbek, wersje detektorów, progi oraz odsetki fałszywych trafień. Podaj niepewność wokół raportowanych wskaźników. Powtarzaj ocenę, gdy zmieniasz klucze, tokenizację, wersje modelu lub ustawienia generowania. Dopóki takie kontrole nie istnieją, opisuj współistnienie i zastępowanie jako niezweryfikowane.

Co to oznacza dla wydawców i widoczności w AI

Wykrywanie znaków wodnych i monitorowanie cytowań AI odpowiadają na różne pytania. Test znaku wodnego pyta, czy fragment niesie dowód konkretnej konfiguracji generowania. Monitorowanie cytowań sprawdza, które źródła pojawiają się w odpowiedziach AI.

Nie przedstawiaj braku znaku wodnego jako dowodu autorstwa człowieka ani wykrytego znaku wodnego jako dowodu, że cytowano konkretną witrynę. W procesach publikowania przechowuj zapisy generowania i przypisanie redakcyjne obok dowolnego detektora statystycznego. Każdy z nich dostarcza dowodów, których nie dają pozostałe.

Przydatne? Podaj dalej.

LinkedIn X

Najczęściej zadawane pytania

Viktor Zeman jest współwłaścicielem QualityUnit. Nawet po 20 latach kierowania firmą pozostaje przede wszystkim inżynierem oprogramowania, specjalizującym się w AI, programatycznym SEO i rozwoju backendu. Współtworzył wiele projektów, w tym LiveAgent, PostAffiliatePro, FlowHunt, UrlsLab i wiele innych.

Viktor Zeman
Viktor Zeman
CEO, AI Engineer

Śledź, gdzie AI cytuje Twoje treści

Wykorzystaj monitorowanie cytowań, aby zrozumieć, na które strony powołują się odpowiedzi AI. Wykrywanie znaków wodnych odpowiada na inne pytanie dotyczące pochodzenia tekstu.

Dowiedz się więcej

Znakowanie treści AI (Watermarking AI Content)
Znakowanie treści AI: definicja, metody i wdrożenie

Znakowanie treści AI (Watermarking AI Content)

Znakowanie treści AI polega na osadzaniu cyfrowych znaczników w materiałach generowanych przez AI w celu weryfikacji autentyczności. Poznaj techniki, regulacje ...

9 min czytania
Wykrywanie treści AI
Wykrywanie treści AI: Narzędzia identyfikujące treści generowane przez sztuczną inteligencję

Wykrywanie treści AI

Dowiedz się, czym jest wykrywanie treści AI, jak działają narzędzia oparte na uczeniu maszynowym i NLP oraz dlaczego są ważne dla monitorowania marki, edukacji ...

12 min czytania