-
Notifications
You must be signed in to change notification settings - Fork 2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
40 changed files
with
1,000,462 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
<p align="center"> | ||
<img src="./assets/logo.png" width="15%"> <br> | ||
</p> | ||
|
||
<div align="center"> | ||
<h1>EasyTool</h1> | ||
<h3>Enhancing LLM-based Agents with Concise Tool Instruction<h3> | ||
</div> | ||
|
||
## Overview | ||
|
||
LLM-based agents usually employ tool documentation to grasp the selection and usage of tools from different sources, but these documentations could be inconsistent in formats, redundant with excessive length, and lacking demonstrations for instructions. | ||
|
||
EasyTool is an easy but effective method to create clear, structured, and unified instructions from tool documentations for improving LLM-based agents in using tools. | ||
|
||
<p align="center"> | ||
<img width="70%" alt="image" src="./assets/front.png"> | ||
</p> | ||
|
||
## Experiment | ||
|
||
### Prerequisites | ||
|
||
- Prepare requirements: `pip install -r requirements.txt` | ||
- Data Construction: `python3 data_process.py` | ||
|
||
Before running any of the commands, ensure that you have set the necessary API keys. Replace `""` with your actual keys. | ||
```bash | ||
export OPENAI_API_KEY="your_openai_api_key_here" | ||
export RAPIDAPI_KEY="your_rapidapi_key_here" | ||
``` | ||
### ToolBench | ||
You need first get the tool execution code (./data/toolenv/tools.) from the following link: [Google Drive](https://drive.google.com/drive/folders/1yBUQ732mPu-KclJnuQELEhtKakdXFc3J) or [Tsinghua Cloud](https://cloud.tsinghua.edu.cn/f/c9e50625743b40bfbe10/) and then save them to ./toolenv/tools | ||
To inference with LLMs, run the following commands: | ||
```bash | ||
unzip data_toolbench/tool_instruction/API_description_embeddings.zip -d data_toolbench/tool_instruction/ | ||
|
||
export OPENAI_API_KEY="" | ||
export RAPIDAPI_KEY="" | ||
|
||
python3 main.py \ | ||
--model_name gpt-3.5-turbo \ | ||
--task toolbench \ | ||
--data_type G2 \ | ||
--tool_root_dir ./toolenv/tools | ||
|
||
python3 main.py \ | ||
--model_name gpt-3.5-turbo \ | ||
--task toolbench \ | ||
--data_type G3 \ | ||
--tool_root_dir ./toolenv/tools | ||
|
||
python3 main.py \ | ||
--model_name gpt-3.5-turbo \ | ||
--task toolbench_retrieve \ | ||
--data_type G2 \ | ||
--tool_root_dir ./toolenv/tools | ||
|
||
python3 main.py \ | ||
--model_name gpt-3.5-turbo \ | ||
--task toolbench_retrieve \ | ||
--data_type G3 \ | ||
--tool_root_dir ./toolenv/tools | ||
``` | ||
|
||
### FuncQA | ||
|
||
To inference with LLMs, run the following commands: | ||
```bash | ||
export OPENAI_API_KEY="" | ||
|
||
python3 main.py \ | ||
--model_name gpt-3.5-turbo \ | ||
--task funcqa \ | ||
--data_type funcqa_mh | ||
|
||
python3 main.py \ | ||
--model_name gpt-3.5-turbo \ | ||
--task funcqa \ | ||
--data_type funcqa_oh | ||
``` | ||
|
||
### RestBench | ||
|
||
To inference with LLMs, run the following commands: | ||
```bash | ||
export OPENAI_API_KEY="" | ||
|
||
python3 main.py \ | ||
--model_name gpt-3.5-turbo \ | ||
--task restbench | ||
``` | ||
|
||
## Acknowledgement | ||
|
||
- [ChatGPT](https://platform.openai.com/) | ||
- [Hugging Face](https://huggingface.co/) | ||
- [ToolBench](https://github.com/OpenBMB/ToolBench) | ||
- [RestBench](https://github.com/Yifan-Song793/RestGPT) | ||
- [FuncQA](https://github.com/Ber666/ToolkenGPT) |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
import math | ||
|
||
# this function is used to round the result to 2 decimal places | ||
# e.g. 52.3523 -> 52.35, 52.0011 -> 52, 0.00000233 -> 0.0000023 | ||
def custom_round(x, decimal_places=2): | ||
str_x = f"{x:.10f}" | ||
before_decimal = str_x.split('.')[0] | ||
after_decimal = str_x.split('.')[1] | ||
leading_zeros = len(after_decimal) - len(after_decimal.lstrip('0')) | ||
|
||
if leading_zeros >= 1 and before_decimal == "0": | ||
return round(x, leading_zeros + 2) | ||
else: | ||
return round(x, decimal_places) | ||
|
||
# this function converts a number in scientific notation to decimal notation | ||
def scito_decimal(sci_str): | ||
def split_exponent(number_str): | ||
parts = number_str.split("e") | ||
coefficient = parts[0] | ||
exponent = int(parts[1]) if len(parts) == 2 else 0 | ||
return coefficient, exponent | ||
|
||
def multiplyby_10(number_str, exponent): | ||
if exponent == 0: | ||
return number_str | ||
|
||
if exponent > 0: | ||
index = number_str.index(".") if "." in number_str else len(number_str) | ||
number_str = number_str.replace(".", "") | ||
new_index = index + exponent | ||
number_str += "0" * (new_index - len(number_str)) | ||
if new_index < len(number_str): | ||
number_str = number_str[:new_index] + "." + number_str[new_index:] | ||
return number_str | ||
|
||
if exponent < 0: | ||
index = number_str.index(".") if "." in number_str else len(number_str) | ||
number_str = number_str.replace(".", "") | ||
new_index = index + exponent | ||
number_str = "0" * (-new_index) + number_str | ||
number_str = "0." + number_str | ||
return number_str | ||
|
||
coefficient, exponent = split_exponent(sci_str) | ||
decimal_str = multiplyby_10(coefficient, exponent) | ||
|
||
# remove trailing zeros | ||
if "." in decimal_str: | ||
decimal_str = decimal_str.rstrip("0") | ||
|
||
return decimal_str | ||
|
||
# normalize the result to 2 decimal places and remove trailing zeros | ||
def normalize(res, round_to=2): | ||
# we round the result to 2 decimal places | ||
res = custom_round(res, round_to) | ||
res = str(res) | ||
if "." in res: | ||
while res[-1] == "0": | ||
res = res[:-1] | ||
res = res.strip(".") | ||
|
||
# scientific notation | ||
if "e" in res: | ||
res = scito_decimal(res) | ||
|
||
return res | ||
|
||
# 1. add | ||
def add_(args): | ||
|
||
return normalize(sum(args)) | ||
|
||
# 2. subtract | ||
def subtract_(args): | ||
|
||
res = args[0] | ||
for arg in args[1:]: | ||
res -= arg | ||
return normalize(res) | ||
|
||
# 3. multiply | ||
def multiply_(args): | ||
|
||
res = args[0] | ||
for arg in args[1:]: | ||
res *= arg | ||
return normalize(res) | ||
|
||
# 4. divide | ||
def divide_(args): | ||
|
||
res = args[0] | ||
for arg in args[1:]: | ||
res /= arg | ||
return normalize(res) | ||
|
||
# 5. power | ||
def power_(args): | ||
|
||
res = args[0] | ||
for arg in args[1:]: | ||
res **= arg | ||
return normalize(res) | ||
|
||
# 6. square root | ||
def sqrt_(args): | ||
res = args[0] | ||
return normalize(math.sqrt(res)) | ||
|
||
# 7. 10th log | ||
def log_(args): | ||
# if only one argument is passed, it is 10th log | ||
if len(args) == 1: | ||
res = args[0] | ||
return normalize(math.log10(res)) | ||
# if two arguments are passed, it is log with base as the second argument | ||
elif len(args) == 2: | ||
res = args[0] | ||
base = args[1] | ||
return normalize(math.log(res, base)) | ||
else: | ||
raise Exception("Invalid number of arguments passed to log function") | ||
|
||
# 8. natural log | ||
def ln_(args): | ||
res = args[0] | ||
return normalize(math.log(res)) | ||
|
||
|
||
# 9. choose | ||
def choose_(args): | ||
n = args[0] | ||
r = args[1] | ||
return normalize(math.comb(n, r)) | ||
|
||
# 10. permutation | ||
def permutate_(args): | ||
n = args[0] | ||
r = args[1] | ||
return normalize(math.perm(n, r)) | ||
|
||
# 11. greatest common divisor | ||
def gcd_(args): | ||
res = args[0] | ||
for arg in args[1:]: | ||
res = math.gcd(res, arg) | ||
return normalize(res) | ||
|
||
# 12. least common multiple | ||
def lcm_(args): | ||
res = args[0] | ||
for arg in args[1:]: | ||
res = res * arg // math.gcd(res, arg) | ||
return normalize(res) | ||
|
||
# 13. remainder | ||
def remainder_(args): | ||
dividend = args[0] | ||
divisor = args[1] | ||
return normalize(dividend % divisor) |
Oops, something went wrong.