Repository: LAION-AI/Open-Assistant
File: inference/worker/chat_chain_utils.py (Python)

Code before:
            logger.warning(f"JSON is still not valid, trying to fix it with LLM {fixed_json}")
            # if it's still not valid, try with LLM fixer
            prompt = f"""{V2_PROMPTER_PREFIX}Below is malformed JSON object string:
--------------
{json_str}
--------------
Parsing error:
--------------
{e}

RULES:
1. If malformed JSON object string contains multiple objects, you merge them into one.
2. You will never made up or add any new data, you will only fix the malformed JSON object string.

Here is the fixed JSON object string:
{V2_ASST_PREFIX}"""
            logger.warning(f"JSON Fix Prompt: {prompt}")
            out = llm_parser.generate(prompts=[prompt]).generations[0][0].text
            out = out[: out.find("}") + 1]
            logger.warning(f"JSON Fix Output: {out}")
            return out

    return fixed_json


def use_tool(tool_name: str, tool_input: str, tools: list) -> str:
    best_match = None
    best_similarity = 0
    for tool in tools:
        tool_similarity = similarity(tool.name, tool_name)
        if tool_similarity > best_similarity:
            best_similarity = tool_similarity
            best_match = tool
    # This should become stricter and stricter as we get better models
    if best_match is not None and best_similarity > 0.75:
        tool_input = prepare_json(tool_input)
        return best_match.func(tool_input)
    return f"ERROR! {tool_name} is not a valid tool. Try again with different tool!"


# Needs more work for errors, error-prompt tweaks are currently based on
# `OpenAssistant/oasst-sft-6-llama-30b-epoch-1 model`
# TODO: Add other missing methods and Content-Types etc...
class RequestsForLLM:
    def run(self, params: str, url: str, param_location: str, type: str, payload: str | None = None) -> str:
        return self.run_request(params, url, param_location, type, payload)

    def run_request(self, params: str, url: str, param_location: str, type: str, payload: str = None) -> str:
        try:
            query_params = params
            if param_location == "path":
                for key, value in query_params.items():

Review comment (suggestion):
This code could just be something like:

```
    best_match, best_similarity = max(
        ((tool, similarity(tool.name, tool_name)) for tool in tools),
        key=lambda x: x[1], 
        default=(None, 0),
    )
```

Code after:
            logger.warning(f"JSON is still not valid, trying to fix it with LLM {fixed_json}")
            # if it's still not valid, try with LLM fixer
            prompt = f"""{V2_PROMPTER_PREFIX}Below is malformed JSON object string:
--------------
{json_str}
--------------
Parsing error:
--------------
{e}

RULES:
1. If malformed JSON object string contains multiple objects, you merge them into one.
2. You will never made up or add any new data, you will only fix the malformed JSON object string.

Here is the fixed JSON object string:
{V2_ASST_PREFIX}"""
            logger.warning(f"JSON Fix Prompt: {prompt}")
            out = llm_parser.generate(prompts=[prompt]).generations[0][0].text
            out = out[: out.find("}") + 1]
            logger.warning(f"JSON Fix Output: {out}")
            return out

    return fixed_json


def use_tool(tool_name: str, tool_input: str, tools: list) -> str:
    best_match, best_similarity = max(
        ((tool, similarity(tool.name, tool_name)) for tool in tools), key=lambda x: x[1], default=(None, 0)
    )
    # This should become stricter and stricter as we get better models
    if best_match is not None and best_similarity > 0.75:
        tool_input = prepare_json(tool_input)
        return best_match.func(tool_input)
    return f"ERROR! {tool_name} is not a valid tool. Try again with different tool!"


# Needs more work for errors, error-prompt tweaks are currently based on
# `OpenAssistant/oasst-sft-6-llama-30b-epoch-1 model`
# TODO: Add other missing methods and Content-Types etc...
class RequestsForLLM:
    def run(self, params: str, url: str, param_location: str, type: str, payload: str | None = None) -> str:
        return self.run_request(params, url, param_location, type, payload)

    def run_request(self, params: str, url: str, param_location: str, type: str, payload: str = None) -> str:
        try:
            query_params = params
            if param_location == "path":
                for key, value in query_params.items():
                    url = url.replace(f"{{{key}}}", value)
                query_params = {}

            headers = {"Content-Type": "application/json"} if payload else None