While testing Garak against a local OpenAI-compatible API endpoint (using oobabooga's text-generation-webui), I encountered an issue with the REST generator's JSON field access. The problem arose when trying to access nested response fields, particularly the completion text located at 'choices[0].text' in the API response.
The fix required modifying how Garak's REST generator handles nested JSON paths.
Here's what a typical API response looks like:
{
"id": "conv-1732143549602938112",
"object": "text_completion",
"choices": [
{
"index": 0,
"finish_reason": "length",
"text": "! When I was in college my best friend turned me on to a spiritual mentor"
}
]
}
The original code attempted to access this nested structure directly, which resulted in a KeyError. The solution was to implement a helper method that could properly traverse nested JSON paths.
Here's the fixed code snippet:
def _get_nested_value(self, obj, path):
"""Helper method to get nested dictionary values using a path string."""
try:
current = obj
parts = path.replace("][", "].").replace("[", ".").replace("]", "").split(".")
for part in parts:
if part.isdigit():
current = current[int(part)]
else:
current = current[part]
return current
except (KeyError, IndexError, TypeError) as e:
logging.error(f"Failed to access path '{path}' in object: {e}")
return None
The fix can be applied in two ways:
pip install -e .
This modification allows Garak to properly handle nested JSON responses from OpenAI-compatible APIs, making it more robust for testing local language models. We got success! Now to begin the long process of actually using the tool for testing.
A key learning from this experience is the importance of properly handling nested data structures when working with API responses. As more organizations deploy local LLMs with OpenAI-compatible APIs, tools like Garak need to handle various response formats effectively.
Remember to use pip's editable install mode (-e flag) during development to make the development process smoother! I needed to increase the token limit in the .json file, and then subsequently increase the timeout in rest.py to account for this.
> End of output.