import gradio as gr import json import os import numexpr from groq import Groq from groq.types.chat.chat_completion_tool_param import ChatCompletionToolParam MODEL = "llama3-groq-70b-8192-tool-use-preview" client = Groq(api_key=os.environ["GROQ_API_KEY"]) def evaluate_math_expression(expression: str): return json.dumps(numexpr.evaluate(expression).tolist()) calculator_tool: ChatCompletionToolParam = { "type": "function", "function": { "name": "evaluate_math_expression", "description": "Calculator tool: use this for evaluating numeric expressions with Python. Ensure the expression is valid Python syntax (e.g., use '**' for exponentiation, not '^').", "parameters": { "type": "object", "properties": { "expression": { "type": "string", "description": "The mathematical expression to evaluate. Must be valid Python syntax.", }, }, "required": ["expression"], }, }, } tools = [calculator_tool] def call_function(tool_call, available_functions): function_name = tool_call.function.name if function_name not in available_functions: return { "tool_call_id": tool_call.id, "role": "tool", "content": f"Function {function_name} does not exist.", } function_to_call = available_functions[function_name] function_args = json.loads(tool_call.function.arguments) function_response = function_to_call(**function_args) return { "tool_call_id": tool_call.id, "role": "tool", "name": function_name, "content": json.dumps(function_response), } def get_model_response(messages, inner_messages, message, system_message): messages_for_model = [] for msg in messages: native_messages = msg.get("metadata", {}).get("native_messages", [msg]) if isinstance(native_messages, list): messages_for_model.extend(native_messages) else: messages_for_model.append(native_messages) messages_for_model.insert( 0, { "role": "system", "content": system_message, }, ) messages_for_model.append( { "role": "user", "content": message, } ) messages_for_model.extend(inner_messages) try: return client.chat.completions.create( model=MODEL, messages=messages_for_model, tools=tools, temperature=0.5, top_p=0.65, max_tokens=4096, ) except Exception as e: print(f"An error occurred while getting model response: {str(e)}") print(messages_for_model) return None def respond(message, history, system_message): inner_history = [] available_functions = { "evaluate_math_expression": evaluate_math_expression, } assistant_content = "" assistant_native_message_list = [] while True: response_message = ( get_model_response(history, inner_history, message, system_message) .choices[0] .message ) if not response_message.tool_calls and response_message.content is not None: break if response_message.tool_calls is not None: assistant_native_message_list.append(response_message) inner_history.append(response_message) assistant_content += ( "```json\n" + json.dumps( [ tool_call.model_dump() for tool_call in response_message.tool_calls ], indent=2, ) + "\n```\n" ) assistant_message = { "role": "assistant", "content": assistant_content, "metadata": {"native_messages": assistant_native_message_list}, } yield assistant_message for tool_call in response_message.tool_calls: function_response = call_function(tool_call, available_functions) assistant_content += ( "```json\n" + json.dumps( { "name": tool_call.function.name, "arguments": json.loads(tool_call.function.arguments), "response": json.loads(function_response["content"]), }, indent=2, ) + "\n```\n" ) native_tool_message = { "tool_call_id": tool_call.id, "role": "tool", "content": function_response["content"], } assistant_native_message_list.append( native_tool_message ) tool_message = { "role": "assistant", "content": assistant_content, "metadata": {"native_messages": assistant_native_message_list}, } yield tool_message inner_history.append(native_tool_message) assistant_content += response_message.content assistant_native_message_list.append(response_message) final_message = { "role": "assistant", "content": assistant_content, "metadata": {"native_messages": assistant_native_message_list}, } yield final_message system_prompt = "You are a friendly Chatbot with access to a calculator. Don't mention that we are using functions defined in Python." demo = gr.ChatInterface( respond, additional_inputs=[ gr.Textbox( value=system_prompt, label="System message", ), ], type="messages", title="Groq Tool Use Chat", description="This chatbot uses the `llama3-groq-70b-8192-tool-use-preview` LLM with tool use capabilities, including a calculator function.", ) if __name__ == "__main__": demo.launch()