Spaces:
Running
Running
| import io | |
| import math | |
| import numexpr | |
| import traceback | |
| from contextlib import redirect_stderr, redirect_stdout | |
| from langchain_core.tools import Tool | |
| from langchain_core.tools import tool | |
| from langgraph.types import interrupt | |
| def calculator(expression: str) -> str: | |
| """Evaluate mathematical expressions safely. | |
| This function provides a safe way to evaluate mathematical expressions | |
| using numexpr. It supports basic mathematical operations and common | |
| mathematical functions. | |
| Parameters | |
| ---------- | |
| expression : str | |
| Mathematical expression to evaluate (e.g., "2 * pi + 5") | |
| Returns | |
| ------- | |
| str | |
| String result or error message | |
| Notes | |
| ----- | |
| Supported mathematical functions: | |
| - Basic operations: +, -, *, /, ** | |
| - Trigonometric: sin, cos, tan | |
| - Other: sqrt, abs | |
| - Constants: pi, e | |
| """ | |
| local_dict = { | |
| "pi": math.pi, | |
| "e": math.e, | |
| "sin": math.sin, | |
| "cos": math.cos, | |
| "tan": math.tan, | |
| "sqrt": math.sqrt, | |
| "abs": abs, | |
| } | |
| try: | |
| cleaned_expression = expression.strip() | |
| if not cleaned_expression: | |
| return "Error: Empty expression" | |
| result = numexpr.evaluate( | |
| cleaned_expression, | |
| global_dict={}, | |
| local_dict=local_dict, | |
| ) | |
| if isinstance(result, (int, float)): | |
| return f"{float(result):.6f}".rstrip("0").rstrip(".") | |
| return str(result) | |
| except Exception as e: | |
| return f"Error evaluating expression: {e!s}" | |
| def ask_human(question: str) -> str: | |
| """Ask the human user for clarification, confirmation, or additional details. | |
| Use this tool when: | |
| - Required inputs are missing or ambiguous (e.g., molecule name, calculator | |
| type, temperature, pressure, or simulation method). | |
| - You need confirmation before running a computationally expensive simulation | |
| (e.g., geometry optimization, vibrational analysis, thermochemistry). | |
| - A previous tool call failed and you need the user to decide how to proceed | |
| (e.g., retry with different parameters, skip the step, or abort). | |
| The graph execution will pause until the human responds. The human's | |
| answer is returned as a string. | |
| Parameters | |
| ---------- | |
| question : str | |
| The question or request to present to the human user. | |
| Returns | |
| ------- | |
| str | |
| The human's response. | |
| """ | |
| response = interrupt({"question": question}) | |
| if isinstance(response, dict): | |
| return response.get("answer", response.get("response", str(response))) | |
| return str(response) | |
| class PythonREPL: | |
| """Small persistent Python REPL used by the python_repl tool.""" | |
| def __init__(self): | |
| """Initialize an empty persistent global namespace.""" | |
| self.globals = {} | |
| def run(self, command: str) -> str: | |
| """Execute Python code in the persistent REPL namespace. | |
| Parameters | |
| ---------- | |
| command : str | |
| Python code to execute. | |
| Returns | |
| ------- | |
| str | |
| Captured stdout/stderr and traceback text, if any. | |
| """ | |
| cleaned_command = command.strip() | |
| if not cleaned_command: | |
| return "" | |
| output = io.StringIO() | |
| try: | |
| with redirect_stdout(output), redirect_stderr(output): | |
| exec(cleaned_command, self.globals, self.globals) | |
| except Exception: | |
| return output.getvalue() + traceback.format_exc() | |
| return output.getvalue() | |
| python_repl = PythonREPL() | |
| repl_tool = Tool( | |
| name="python_repl", | |
| description="A Python shell. Use this to execute python commands. Input should be a valid python command. If you want to see the output of a value, you should print it out with `print(...)`.", | |
| func=python_repl.run, | |
| ) | |