mirror of
https://github.com/OS-Copilot/OS-Copilot.git
synced 2026-05-05 03:00:15 -04:00
Merge branch 'new_infra_hcc' into dev_wzm
This commit is contained in:
12
code_temp.py
Normal file
12
code_temp.py
Normal file
@@ -0,0 +1,12 @@
|
||||
from itertools import permutations
|
||||
cities = {'Hangzhou': 1, 'Shanghai': 3, 'Wuhan': 3, 'Chengdu': 1}
|
||||
city_permutations = permutations(cities.keys())
|
||||
best_sequence = None
|
||||
min_days_spent = float('inf')
|
||||
for perm in city_permutations:
|
||||
days_spent = sum(cities[city] for city in perm)
|
||||
if days_spent < min_days_spent:
|
||||
min_days_spent = days_spent
|
||||
best_sequence = perm
|
||||
print(f'Best sequence: {best_sequence}')
|
||||
print(f'Minimum days spent: {min_days_spent}')
|
||||
@@ -2,6 +2,7 @@ from jarvis.agent.openai_agent import OpenAIAgent
|
||||
from jarvis.enviroment.old_env import BaseEnviroment
|
||||
from jarvis.enviroment.py_env import PythonEnv
|
||||
from jarvis.enviroment.bash_env import BashEnv
|
||||
import time
|
||||
'''
|
||||
Made By WZM
|
||||
用处:查看指定区域这几天的天气
|
||||
@@ -9,7 +10,7 @@ Made By WZM
|
||||
|
||||
# environment = BaseEnviroment()
|
||||
environment = PythonEnv()
|
||||
agent = OpenAIAgent(config_path="config.json")
|
||||
agent = OpenAIAgent(config_path="examples/config.json")
|
||||
|
||||
response = '''
|
||||
Thought: To set up the working environment, we can focus on two sub-goals: turning on dark mode and organizing the app layout.
|
||||
@@ -22,7 +23,7 @@ Actions:
|
||||
action = agent.extract_action(response, begin_str='<action>', end_str='</action>')
|
||||
invoke = agent.extract_action(response, begin_str='<invoke>', end_str='</invoke>')
|
||||
print(invoke)
|
||||
import time
|
||||
|
||||
for (i,a) in enumerate(action):
|
||||
command = agent.action_lib[a] + "\n" + invoke[i]
|
||||
# print(a, command)
|
||||
|
||||
@@ -1,12 +1,20 @@
|
||||
from jarvis.action.base_action import BaseAction
|
||||
# from jarvis.atom_action.operations.system import terminal_show_file_content
|
||||
# import requests
|
||||
import subprocess
|
||||
|
||||
def enable_do_not_disturb():
|
||||
# This function uses AppleScript to enable Do Not Disturb mode on a Mac.
|
||||
applescript = f"""
|
||||
tell application "Shortcuts Events"
|
||||
run shortcut "enable_do_not_disturb"
|
||||
end tell
|
||||
"""
|
||||
subprocess.run(["osascript", "-e", applescript])
|
||||
|
||||
enable_do_not_disturb()
|
||||
class enable_do_not_disturb(BaseAction):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
self._description = "enable do not disturb mode"
|
||||
self.action_type = 'Python'
|
||||
|
||||
def __call__(self) -> None:
|
||||
# This function uses AppleScript to enable Do Not Disturb mode on a Mac.
|
||||
applescript = f"""
|
||||
tell application "Shortcuts Events"
|
||||
run shortcut "enable_do_not_disturb"
|
||||
end tell
|
||||
"""
|
||||
subprocess.run(["osascript", "-e", applescript])
|
||||
@@ -1,12 +1,32 @@
|
||||
from jarvis.action.base_action import BaseAction
|
||||
# from jarvis.atom_action.operations.system import terminal_show_file_content
|
||||
# import requests
|
||||
import subprocess
|
||||
|
||||
def play_light_music():
|
||||
# Plays a playlist named "light music" in iTunes or Music app
|
||||
applescript = """
|
||||
tell application "Music"
|
||||
play playlist "light music"
|
||||
end tell
|
||||
"""
|
||||
subprocess.run(["osascript", "-e", applescript])
|
||||
|
||||
play_light_music()
|
||||
class play_light_music(BaseAction):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
self._description = "play light music"
|
||||
self.action_type = 'Python'
|
||||
|
||||
def __call__(self) -> None:
|
||||
# This function uses AppleScript to enable Do Not Disturb mode on a Mac.
|
||||
applescript = """
|
||||
tell application "Music"
|
||||
play playlist "light music"
|
||||
end tell
|
||||
"""
|
||||
subprocess.run(["osascript", "-e", applescript])
|
||||
|
||||
|
||||
# def play_light_music():
|
||||
# # Plays a playlist named "light music" in iTunes or Music app
|
||||
# applescript = """
|
||||
# tell application "Music"
|
||||
# play playlist "light music"
|
||||
# end tell
|
||||
# """
|
||||
# subprocess.run(["osascript", "-e", applescript])
|
||||
|
||||
# play_light_music()
|
||||
@@ -1,22 +1,50 @@
|
||||
from jarvis.action.base_action import BaseAction
|
||||
# from jarvis.atom_action.operations.system import terminal_show_file_content
|
||||
# import requests
|
||||
import subprocess
|
||||
import datetime
|
||||
|
||||
def set_20_minute_alarm():
|
||||
# Sets an alarm for 20 minutes from now using AppleScript
|
||||
# The script creates a new reminder with an alert
|
||||
current_time = datetime.datetime.now()
|
||||
alarm_time = current_time + datetime.timedelta(minutes=20)
|
||||
alarm_time_str = alarm_time.strftime('%Y-%m-%d %H:%M:%S')
|
||||
|
||||
applescript = f"""
|
||||
tell application "Reminders"
|
||||
set newReminder to make new reminder
|
||||
tell newReminder
|
||||
set name to "20 Minute Alarm"
|
||||
set remind me date to date "{alarm_time_str}"
|
||||
class set_20_minute_alarm(BaseAction):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
self._description = "set 20 minute alarm"
|
||||
self.action_type = 'Python'
|
||||
|
||||
def __call__(self) -> None:
|
||||
# Sets an alarm for 20 minutes from now using AppleScript
|
||||
# The script creates a new reminder with an alert
|
||||
current_time = datetime.datetime.now()
|
||||
alarm_time = current_time + datetime.timedelta(minutes=20)
|
||||
alarm_time_str = alarm_time.strftime('%Y-%m-%d %H:%M:%S')
|
||||
|
||||
applescript = f"""
|
||||
tell application "Reminders"
|
||||
set newReminder to make new reminder
|
||||
tell newReminder
|
||||
set name to "20 Minute Alarm"
|
||||
set remind me date to date "{alarm_time_str}"
|
||||
end tell
|
||||
end tell
|
||||
end tell
|
||||
"""
|
||||
subprocess.run(["osascript", "-e", applescript])
|
||||
"""
|
||||
subprocess.run(["osascript", "-e", applescript])
|
||||
|
||||
set_20_minute_alarm()
|
||||
# def set_20_minute_alarm():
|
||||
# # Sets an alarm for 20 minutes from now using AppleScript
|
||||
# # The script creates a new reminder with an alert
|
||||
# current_time = datetime.datetime.now()
|
||||
# alarm_time = current_time + datetime.timedelta(minutes=20)
|
||||
# alarm_time_str = alarm_time.strftime('%Y-%m-%d %H:%M:%S')
|
||||
|
||||
# applescript = f"""
|
||||
# tell application "Reminders"
|
||||
# set newReminder to make new reminder
|
||||
# tell newReminder
|
||||
# set name to "20 Minute Alarm"
|
||||
# set remind me date to date "{alarm_time_str}"
|
||||
# end tell
|
||||
# end tell
|
||||
# """
|
||||
# subprocess.run(["osascript", "-e", applescript])
|
||||
|
||||
# set_20_minute_alarm()
|
||||
|
||||
@@ -32,7 +32,7 @@ class BaseAgent:
|
||||
source_code = inspect.getsource(module) # wzm修改,通过自省获得文件源码
|
||||
tmp_obj = getattr(module, class_name)() #存储对象方式
|
||||
# 存储源码字符串
|
||||
self.action_lib.update({class_name: source_code })# wzm修改,技能库存储文件源码而不是对象
|
||||
self.action_lib.update({class_name: source_code})# wzm修改,技能库存储文件源码而不是对象
|
||||
# self.action_lib.update({class_name: tmp_obj})
|
||||
self.action_lib_description.update({class_name: tmp_obj.description})
|
||||
|
||||
|
||||
311
jarvis/agent/react_agent.py
Normal file
311
jarvis/agent/react_agent.py
Normal file
@@ -0,0 +1,311 @@
|
||||
import json
|
||||
import re
|
||||
import os
|
||||
import ast
|
||||
import time
|
||||
import openai
|
||||
import copy
|
||||
import requests
|
||||
from collections import defaultdict
|
||||
|
||||
from jarvis.core.prompt import TRAVEL_SYSTEM_PROMPT, TRAVEL_USER_FIRST, TRAVEL_USER_OVER_PROMPT, TRAVEL_USER_PROMPT, TRAVEL_EXAMPLE_MESSAGES_1
|
||||
# from agents.base_agent import BaseAgent
|
||||
# from utils.prompt import generate_prompt
|
||||
# from utils.api_service import chat_gpt
|
||||
|
||||
|
||||
class BaseAgent:
|
||||
def __init__(self, record_path=None, model_name='gpt-3.5-turbo', proxy='http://127.0.0.1:10809'):
|
||||
self.system_prompt = None
|
||||
self.messages = []
|
||||
self.subtasks = []
|
||||
self.model_name = model_name
|
||||
self.proxy = proxy
|
||||
self.record_path = record_path
|
||||
|
||||
def chat_gpt(self, messages, model_name="gpt-3.5-turbo-16k-0613", sleep_time=2, temperature=0,proxy=None):
|
||||
# if proxy is not None:
|
||||
# os.environ["http_proxy"] = proxy
|
||||
# os.environ["https_proxy"] = proxy
|
||||
|
||||
openai.api_key = os.getenv("OPENAI_API_KEY")
|
||||
org=os.getenv("OPENAI_ORGANIZATION")
|
||||
print(f'message[-1]={messages[-1]}')
|
||||
if org is not None:
|
||||
openai.organization=org
|
||||
try:
|
||||
response = openai.chat.completions.create(
|
||||
model=model_name,
|
||||
messages=messages,
|
||||
temperature=temperature,
|
||||
timeout=60
|
||||
)
|
||||
except openai.RateLimitError as e:
|
||||
print(e)
|
||||
time.sleep(60)
|
||||
response = openai.ChatCompletion.create(
|
||||
model=model_name,
|
||||
messages=messages,
|
||||
temperature=temperature,
|
||||
timeout=60
|
||||
)
|
||||
except openai.InternalServerError as e2:
|
||||
print(e2)
|
||||
time.sleep(60)
|
||||
response = openai.ChatCompletion.create(
|
||||
model=model_name,
|
||||
messages=messages,
|
||||
temperature=temperature,
|
||||
timeout=60
|
||||
)
|
||||
print(f'response={response}')
|
||||
time.sleep(sleep_time)
|
||||
# if proxy is not None:
|
||||
# os.environ.pop("http_proxy", None)
|
||||
# os.environ.pop("https_proxy", None)
|
||||
|
||||
return {'role': response.choices[0].message.role, 'content': response.choices[0].message.content}
|
||||
|
||||
|
||||
def gpt_4(self, messages, model_name="gpt-4-1106-preview", sleep_time=2, temperature=0, session=None, proxy=None):
|
||||
openai.api_key = os.getenv("OPENAI_API_KEY")
|
||||
url = "https://api.openai-hk.com/v1/chat/completions"
|
||||
|
||||
headers = {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": "Bearer {}".format(openai.api_key)
|
||||
}
|
||||
|
||||
data = {
|
||||
"max_tokens": 1200,
|
||||
"model": model_name,
|
||||
"temperature": temperature,
|
||||
"top_p": 1,
|
||||
"presence_penalty": 1,
|
||||
"messages": messages
|
||||
}
|
||||
|
||||
response = session.post(url, headers=headers, data=json.dumps(data).encode('utf-8') )
|
||||
result = response.content.decode("utf-8")
|
||||
|
||||
print(f'response={result}')
|
||||
result = ast.literal_eval(result)
|
||||
time.sleep(sleep_time)
|
||||
return {'role': result['choices'][0]['message']['role'], 'content': result['choices'][0]['message']['content']}
|
||||
|
||||
|
||||
|
||||
def parse_functions(self, text):
|
||||
def extract_functions(text: str, begin="<action>", end='</action>') -> list:
|
||||
# 提取所有被 <action> 和 </action> 包围的内容
|
||||
actions = re.findall(f"{re.escape(begin)}(.*?){re.escape(end)}", text, re.DOTALL)
|
||||
|
||||
result = []
|
||||
for action in actions:
|
||||
# 匹配函数名和参数
|
||||
match = re.match(r"(\w+)\((.*?)\)$", action.strip(), re.DOTALL)
|
||||
if match:
|
||||
function_name, args = match.groups()
|
||||
args = args.strip()
|
||||
# 处理参数字符串,保证它们被引号包围
|
||||
if args:
|
||||
# 匹配由三重引号包围的多行字符串
|
||||
multi_line_str_match = re.match(r"(['\"]{3})(.*?)\1", args, re.DOTALL)
|
||||
if multi_line_str_match:
|
||||
args = [multi_line_str_match.group(2)]
|
||||
else:
|
||||
# 分割参数,并去除两侧的空白和引号
|
||||
args = [arg.strip().strip('"').strip("'") for arg in args.split(',')]
|
||||
else:
|
||||
args = []
|
||||
|
||||
result.append({
|
||||
"function_name": function_name,
|
||||
"args": args
|
||||
})
|
||||
|
||||
return result
|
||||
|
||||
# def extract_functions(text: str, begin="<action>", end='</action>') -> list:
|
||||
# action_patterns = re.findall(rf'{begin}(.*?){end}', text, re.DOTALL)
|
||||
# result = []
|
||||
#
|
||||
# for pattern in action_patterns:
|
||||
# # 提取函数名称和参数
|
||||
# match = re.match(r'([a-zA-Z_][a-zA-Z0-9_]*)\s*\((.*)\)', pattern, re.DOTALL)
|
||||
#
|
||||
# if match:
|
||||
# function_name = match.group(1)
|
||||
# args_raw = match.group(2).strip()
|
||||
#
|
||||
# # 检查是否存在参数
|
||||
# if args_raw == "" or re.match(r'^[\'"].*[\'"]$', args_raw, re.DOTALL):
|
||||
# # 手动解析参数
|
||||
# delimiter_stack = []
|
||||
# current_arg = ""
|
||||
# args = []
|
||||
# escape = False
|
||||
# for char in args_raw:
|
||||
# if char == "\\" and not escape:
|
||||
# escape = True
|
||||
# current_arg += char
|
||||
# continue
|
||||
#
|
||||
# if escape:
|
||||
# escape = False
|
||||
# current_arg += char
|
||||
# continue
|
||||
#
|
||||
# if char in ["'", '"'] and (not delimiter_stack or delimiter_stack[-1] == char):
|
||||
# if delimiter_stack and delimiter_stack[-1] == char:
|
||||
# delimiter_stack.pop()
|
||||
# else:
|
||||
# delimiter_stack.append(char)
|
||||
# current_arg += char
|
||||
# elif char == "," and not delimiter_stack:
|
||||
# args.append(current_arg.strip(" '\""))
|
||||
# current_arg = ""
|
||||
# else:
|
||||
# current_arg += char
|
||||
#
|
||||
# if current_arg:
|
||||
# args.append(current_arg.strip(" '\""))
|
||||
#
|
||||
# result.append({
|
||||
# "function_name": function_name,
|
||||
# "args": args
|
||||
# })
|
||||
# return result
|
||||
|
||||
functions = extract_functions(text=text)
|
||||
return functions
|
||||
|
||||
|
||||
def get_action_space(self):
|
||||
# 使用正则表达式来匹配所有的action
|
||||
action_pattern = re.compile(r'<action>(.*?)\((.*?)\)</action>')
|
||||
actions = action_pattern.findall(self.system_prompt)
|
||||
|
||||
# 用于存储action和其参数
|
||||
action_dict = defaultdict(list)
|
||||
|
||||
for action_name, params in actions:
|
||||
params_list = params.split(',') if params else []
|
||||
params_list = [param.strip() for param in params_list]
|
||||
# 记录参数数量最多的action
|
||||
if len(params_list) > len(action_dict[action_name]):
|
||||
action_dict[action_name] = params_list
|
||||
|
||||
# 构建最终的action list
|
||||
result = []
|
||||
for action_name, params in action_dict.items():
|
||||
if params:
|
||||
action_str = f'<action>{action_name}({", ".join(params)})</action>'
|
||||
else:
|
||||
action_str = f'<action>{action_name}()</action>'
|
||||
result.append(action_str)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def get_subtasks(self, text):
|
||||
pattern = r'<subtask>(.*?)<\/subtask>'
|
||||
matches = re.findall(pattern, text, re.DOTALL)
|
||||
subtasks = []
|
||||
for match in matches:
|
||||
subtask_data = json.loads(match)
|
||||
subtasks.append(subtask_data)
|
||||
return subtasks
|
||||
|
||||
|
||||
def get_subtask_idx(self, subtask_name):
|
||||
for i, subtask in enumerate(self.subtasks):
|
||||
if subtask["subtask_name"] == subtask_name:
|
||||
return i
|
||||
return -1
|
||||
|
||||
|
||||
def add_subtask(self, subtasks):
|
||||
for subtask in subtasks:
|
||||
idx = self.get_subtask_idx(subtask['subtask_name'])
|
||||
if idx >= 0:
|
||||
self.subtasks[idx] = subtask
|
||||
else:
|
||||
self.subtasks.append(subtask)
|
||||
|
||||
|
||||
def add_user_prompt(self, observation):
|
||||
self.messages.append({'role': 'user', 'content': f'{observation}'})
|
||||
|
||||
|
||||
def add_user_error_prompt(self, observation):
|
||||
self.add_user_prompt(observation)
|
||||
|
||||
|
||||
def get_response(self, session):
|
||||
if 'gpt-4' in self.model_name:
|
||||
response = self.gpt_4(messages=self.messages, model_name=self.model_name, session=session, proxy=self.proxy)
|
||||
else:
|
||||
response = self.chat_gpt(messages=self.messages, model_name=self.model_name, proxy=self.proxy)
|
||||
self.messages.append(response)
|
||||
if self.record_path is not None:
|
||||
with open(self.record_path, 'w', encoding='utf-8') as f:
|
||||
json.dump(self.messages, f, indent=4, ensure_ascii=False)
|
||||
subtasks = self.get_subtasks(response['content'])
|
||||
self.add_subtask(subtasks)
|
||||
return response
|
||||
|
||||
|
||||
class ReactAgent(BaseAgent):
|
||||
def __init__(self, task, record_path=None, model_name='gpt-3.5-turbo', proxy='http://127.0.0.1:10809',example_message=TRAVEL_EXAMPLE_MESSAGES_1):
|
||||
super().__init__(record_path=record_path, model_name=model_name, proxy=proxy)
|
||||
self.task = task
|
||||
self.subtasks = []
|
||||
self.completed_tasks = []
|
||||
self.system_prompt = self.generate_system_prompt()
|
||||
self.messages.append({'role': 'system',
|
||||
'content': self.system_prompt})
|
||||
self.action_apace = self.get_action_space()
|
||||
self.messages.extend(example_message)
|
||||
self.messages.append({'role': 'user',
|
||||
'content': self.generate_first_user_prompt(task=self.task)})
|
||||
|
||||
|
||||
def generate_prompt(self, template: str, replace_dict: dict):
|
||||
prompt = copy.deepcopy(template)
|
||||
for k, v in replace_dict.items():
|
||||
prompt = prompt.replace(k, str(v))
|
||||
return prompt
|
||||
|
||||
|
||||
def generate_system_prompt(self):
|
||||
system_prompt = TRAVEL_SYSTEM_PROMPT
|
||||
replace_dict = {
|
||||
}
|
||||
return self.generate_prompt(template=system_prompt, replace_dict=replace_dict)
|
||||
|
||||
|
||||
def generate_first_user_prompt(self, task):
|
||||
user_prompt = TRAVEL_USER_FIRST
|
||||
replace_dict = {
|
||||
'{{task}}': task
|
||||
}
|
||||
return self.generate_prompt(template=user_prompt, replace_dict=replace_dict)
|
||||
|
||||
|
||||
def add_user_prompt(self, observation):
|
||||
user_prompt = TRAVEL_USER_PROMPT
|
||||
replace_dict = {
|
||||
'{{observation}}': observation,
|
||||
'{{action_space}}': str(self.action_apace)
|
||||
}
|
||||
prompt = self.generate_prompt(template=user_prompt, replace_dict=replace_dict)
|
||||
self.messages.append({'role': 'user', 'content': prompt})
|
||||
|
||||
|
||||
def add_over_prompt(self):
|
||||
self.messages.append({'role': 'user', 'content': TRAVEL_USER_OVER_PROMPT})
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
react_agent = ReactAgent()
|
||||
0
jarvis/api/__init__.py
Normal file
0
jarvis/api/__init__.py
Normal file
0
jarvis/api/arxiv/__init__.py
Normal file
0
jarvis/api/arxiv/__init__.py
Normal file
37
jarvis/api/arxiv/arxiv.py
Normal file
37
jarvis/api/arxiv/arxiv.py
Normal file
@@ -0,0 +1,37 @@
|
||||
from fastapi import APIRouter
|
||||
from pydantic import BaseModel
|
||||
import arxiv
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
class ArxivQuery(BaseModel):
|
||||
query: str
|
||||
|
||||
|
||||
top_k_results: int = 3
|
||||
ARXIV_MAX_QUERY_LENGTH = 300
|
||||
doc_content_chars_max: int = 4000
|
||||
|
||||
|
||||
@router.get("/tools/arxiv")
|
||||
async def get_arxiv_article_information(item: ArxivQuery):
|
||||
'''Run Arxiv search and get the article meta information.
|
||||
'''
|
||||
try:
|
||||
results = arxiv.Search( # type: ignore
|
||||
item.query[: ARXIV_MAX_QUERY_LENGTH], max_results=top_k_results
|
||||
).results()
|
||||
except Exception as ex:
|
||||
return {"result": None, "error": f"Arxiv exception: {ex}"}
|
||||
|
||||
docs = [
|
||||
f"Published: {result.updated.date()}\nTitle: {result.title}\n"
|
||||
f"Authors: {', '.join(a.name for a in result.authors)}\n"
|
||||
f"Summary: {result.summary}"
|
||||
for result in results
|
||||
]
|
||||
if docs:
|
||||
return {"result": "\n\n".join(docs)[: doc_content_chars_max], "error": None}
|
||||
else:
|
||||
return {"result": None, "error": "No good Arxiv Result was found"}
|
||||
8
jarvis/api/arxiv/test.py
Normal file
8
jarvis/api/arxiv/test.py
Normal file
@@ -0,0 +1,8 @@
|
||||
import requests
|
||||
|
||||
response = requests.get(
|
||||
'http://127.0.0.1:8079/tools/arxiv',
|
||||
json={'query': 'OpenICL'}
|
||||
)
|
||||
|
||||
print(response.json())
|
||||
0
jarvis/api/bing/__init__.py
Normal file
0
jarvis/api/bing/__init__.py
Normal file
57
jarvis/api/bing/bing_api.py
Normal file
57
jarvis/api/bing/bing_api.py
Normal file
@@ -0,0 +1,57 @@
|
||||
import requests
|
||||
from bs4 import BeautifulSoup
|
||||
from typing import Tuple
|
||||
from enum import Enum
|
||||
|
||||
SEARCH_RESULT_LIST_CHUNK_SIZE = 3
|
||||
RESULT_TARGET_PAGE_PER_TEXT_COUNT = 500
|
||||
|
||||
|
||||
class BingAPI:
|
||||
def __init__(self, subscription_key: str) -> None:
|
||||
self._headers = {
|
||||
'Ocp-Apim-Subscription-Key': subscription_key
|
||||
}
|
||||
self._endpoint = "https://api.bing.microsoft.com/v7.0/search"
|
||||
self._mkt = 'en-US'
|
||||
|
||||
def search(self, key_words: str, max_retry: int = 3):
|
||||
for _ in range(max_retry):
|
||||
try:
|
||||
result = requests.get(self._endpoint, headers=self._headers, params={'q': key_words, 'mkt': self._mkt},
|
||||
timeout=10)
|
||||
except Exception:
|
||||
continue
|
||||
if result.status_code == 200:
|
||||
result = result.json()
|
||||
return result
|
||||
else:
|
||||
continue
|
||||
raise RuntimeError("Failed to access Bing Search API.")
|
||||
|
||||
def load_page(self, url: str, max_retry: int = 3) -> Tuple[bool, str]:
|
||||
for _ in range(max_retry):
|
||||
try:
|
||||
res = requests.get(url, timeout=15)
|
||||
if res.status_code == 200:
|
||||
res.raise_for_status()
|
||||
else:
|
||||
raise RuntimeError("Failed to load page, code {}".format(res.status_code))
|
||||
except Exception:
|
||||
res = None
|
||||
continue
|
||||
res.encoding = res.apparent_encoding
|
||||
content = res.text
|
||||
break
|
||||
if res is None:
|
||||
return False, "Timeout for loading this page, Please try to load another one or search again."
|
||||
try:
|
||||
soup = BeautifulSoup(content, 'html.parser')
|
||||
paragraphs = soup.find_all('p')
|
||||
page_detail = ""
|
||||
for p in paragraphs:
|
||||
text = p.get_text().strip()
|
||||
page_detail += text
|
||||
return True, page_detail
|
||||
except Exception:
|
||||
return False, "Timeout for loading this page, Please try to load another one or search again."
|
||||
32
jarvis/api/bing/bing_service.py
Normal file
32
jarvis/api/bing/bing_service.py
Normal file
@@ -0,0 +1,32 @@
|
||||
from fastapi import APIRouter, HTTPException
|
||||
from pydantic import BaseModel
|
||||
from typing import Optional
|
||||
from .bing_api import BingAPI
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
bing_api = BingAPI('885e62a126554fb390af88ae31d2c8ff')
|
||||
|
||||
class QueryItem(BaseModel):
|
||||
query: str
|
||||
|
||||
class PageItem(BaseModel):
|
||||
url: str
|
||||
|
||||
@router.get("/tools/bing/search")
|
||||
async def bing_search(item: QueryItem):
|
||||
try:
|
||||
search_results = bing_api.search(item.query)
|
||||
except RuntimeError as e:
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
return search_results
|
||||
|
||||
@router.get("/tools/bing/load_page")
|
||||
async def load_page(item: PageItem):
|
||||
try:
|
||||
page_loaded, page_detail = bing_api.load_page(item.url)
|
||||
except RuntimeError as e:
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
if not page_loaded:
|
||||
raise HTTPException(status_code=500, detail=page_detail)
|
||||
return {"page_content": page_detail}
|
||||
13
jarvis/api/bing/test.py
Normal file
13
jarvis/api/bing/test.py
Normal file
@@ -0,0 +1,13 @@
|
||||
import requests
|
||||
|
||||
response = requests.get(
|
||||
'http://127.0.0.1:8079/tools/bing/search',
|
||||
json={'query': 'Python'}
|
||||
)
|
||||
print(response.json())
|
||||
|
||||
response = requests.get(
|
||||
'http://127.0.0.1:8079/tools/bing/load_page',
|
||||
json={'url': 'https://www.python.org/'}
|
||||
)
|
||||
print(response.json())
|
||||
0
jarvis/api/calculator/__init__.py
Normal file
0
jarvis/api/calculator/__init__.py
Normal file
18
jarvis/api/calculator/calculator.py
Normal file
18
jarvis/api/calculator/calculator.py
Normal file
@@ -0,0 +1,18 @@
|
||||
from fastapi import APIRouter, HTTPException
|
||||
from pydantic import BaseModel
|
||||
from simpleeval import simple_eval, SimpleEval
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
class Expression(BaseModel):
|
||||
expression: str
|
||||
|
||||
|
||||
@router.post("/tools/calculator")
|
||||
def evaluate(expression: Expression):
|
||||
try:
|
||||
s = SimpleEval()
|
||||
result = s.eval(expression.expression)
|
||||
return {"result": str(result), "error": None}
|
||||
except Exception as e:
|
||||
return {"result": None, "error": str(e)}
|
||||
10
jarvis/api/calculator/test.py
Normal file
10
jarvis/api/calculator/test.py
Normal file
@@ -0,0 +1,10 @@
|
||||
import requests
|
||||
import json
|
||||
|
||||
# 测试加法
|
||||
expression = "((46210 - 8*9068) / (2 - x))"
|
||||
response = requests.post(
|
||||
'http://127.0.0.1:8079/tools/calculator',
|
||||
json={'expression': expression}
|
||||
)
|
||||
print(response.json())
|
||||
0
jarvis/api/chemical/__init__.py
Normal file
0
jarvis/api/chemical/__init__.py
Normal file
99
jarvis/api/chemical/chemical.py
Normal file
99
jarvis/api/chemical/chemical.py
Normal file
@@ -0,0 +1,99 @@
|
||||
import random
|
||||
|
||||
from fastapi import APIRouter
|
||||
from pydantic import BaseModel
|
||||
from typing import List, Optional, Union
|
||||
from .chemical_prop_api import ChemicalPropAPI
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
class GetNameResponse(BaseModel):
|
||||
"""name list"""
|
||||
names: List[str]
|
||||
|
||||
|
||||
class GetStructureResponse(BaseModel):
|
||||
"""structure list"""
|
||||
state: int
|
||||
content: Optional[str] = None
|
||||
|
||||
|
||||
class GetIDResponse(BaseModel):
|
||||
state: int
|
||||
content: Union[str, List[str]]
|
||||
|
||||
|
||||
chemical_prop_api = ChemicalPropAPI
|
||||
|
||||
|
||||
@router.get("/tools/chemical/get_name", response_model=GetNameResponse)
|
||||
def get_name(cid: str):
|
||||
"""prints the possible 3 synonyms of the queried compound ID"""
|
||||
ans = chemical_prop_api.get_name_by_cid(cid, top_k=3)
|
||||
return {
|
||||
"names": ans
|
||||
}
|
||||
|
||||
|
||||
@router.get("/tools/chemical/get_allname", response_model=GetNameResponse)
|
||||
def get_allname(cid: str):
|
||||
"""prints all the possible synonyms (might be too many, use this function carefully).
|
||||
"""
|
||||
ans = chemical_prop_api.get_name_by_cid(cid)
|
||||
return {
|
||||
"names": ans
|
||||
}
|
||||
|
||||
|
||||
@router.get("/tools/chemical/get_id_by_struct", response_model=GetIDResponse)
|
||||
def get_id_by_struct(smiles: str):
|
||||
"""prints the ID of the queried compound SMILES. This should only be used if smiles is provided or retrieved in the previous step. The input should not be a string, but a SMILES formula.
|
||||
"""
|
||||
cids = chemical_prop_api.get_cid_by_struct(smiles)
|
||||
if len(cids) == 0:
|
||||
return {
|
||||
"state": "no result"
|
||||
}
|
||||
else:
|
||||
return {
|
||||
"state": "matched",
|
||||
"content": cids[0]
|
||||
}
|
||||
|
||||
|
||||
@router.get("/tools/chemical/get_id", response_model=GetIDResponse)
|
||||
def get_id(name: str):
|
||||
"""prints the ID of the queried compound name, and prints the possible 5 names if the queried name can not been precisely matched,
|
||||
"""
|
||||
cids = chemical_prop_api.get_cid_by_name(name)
|
||||
if len(cids) > 0:
|
||||
return {
|
||||
"state": "precise",
|
||||
"content": cids[0]
|
||||
}
|
||||
|
||||
cids = chemical_prop_api.get_cid_by_name(name, name_type="word")
|
||||
if len(cids) > 0:
|
||||
if name in get_name(cids[0]):
|
||||
return {
|
||||
"state": "precise",
|
||||
"content": cids[0]
|
||||
}
|
||||
|
||||
ans = []
|
||||
random.shuffle(cids)
|
||||
for cid in cids[:5]:
|
||||
nms = get_name(cid)
|
||||
ans.append(nms)
|
||||
return {
|
||||
"state": "not precise",
|
||||
"content": ans
|
||||
}
|
||||
|
||||
|
||||
@router.get("/tools/chemical/get_prop")
|
||||
def get_prop(cid: str):
|
||||
"""prints the properties of the queried compound ID
|
||||
"""
|
||||
return chemical_prop_api.get_prop_by_cid(cid)
|
||||
51
jarvis/api/chemical/chemical_prop_api.py
Normal file
51
jarvis/api/chemical/chemical_prop_api.py
Normal file
@@ -0,0 +1,51 @@
|
||||
import json
|
||||
from typing import Optional, List
|
||||
|
||||
import requests
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
|
||||
class ChemicalPropAPI:
|
||||
def __init__(self) -> None:
|
||||
self._endpoint = "https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/"
|
||||
|
||||
def get_name_by_cid(self, cid: str, top_k: Optional[int] = None) -> List[str]:
|
||||
html_doc = requests.get(f"{self._endpoint}cid/{cid}/synonyms/XML").text
|
||||
soup = BeautifulSoup(html_doc, "html.parser", from_encoding="utf-8")
|
||||
syns = soup.find_all('synonym')
|
||||
ans = []
|
||||
if top_k is None:
|
||||
top_k = len(syns)
|
||||
for syn in syns[:top_k]:
|
||||
ans.append(syn.text)
|
||||
return ans
|
||||
|
||||
def get_cid_by_struct(self, smiles: str) -> List[str]:
|
||||
html_doc = requests.get(f"{self._endpoint}smiles/{smiles}/cids/XML").text
|
||||
soup = BeautifulSoup(html_doc, "html.parser", from_encoding="utf-8")
|
||||
cids = soup.find_all('cid')
|
||||
if cids is None:
|
||||
return []
|
||||
ans = []
|
||||
for cid in cids:
|
||||
ans.append(cid.text)
|
||||
return ans
|
||||
|
||||
def get_cid_by_name(self, name: str, name_type: Optional[str] = None) -> List[str]:
|
||||
url = f"{self._endpoint}name/{name}/cids/XML"
|
||||
if name_type is not None:
|
||||
url += f"?name_type={name_type}"
|
||||
html_doc = requests.get(url).text
|
||||
soup = BeautifulSoup(html_doc, "html.parser", from_encoding="utf-8")
|
||||
cids = soup.find_all('cid')
|
||||
if cids is None:
|
||||
return []
|
||||
ans = []
|
||||
for cid in cids:
|
||||
ans.append(cid.text)
|
||||
return ans
|
||||
|
||||
def get_prop_by_cid(self, cid: str) -> str:
|
||||
html_doc = requests.get(
|
||||
f"{self._endpoint}cid/{cid}/property/MolecularFormula,MolecularWeight,CanonicalSMILES,IsomericSMILES,IUPACName,XLogP,ExactMass,MonoisotopicMass,TPSA,Complexity,Charge,HBondDonorCount,HBondAcceptorCount,RotatableBondCount,HeavyAtomCount,CovalentUnitCount/json").text
|
||||
return json.loads(html_doc)['PropertyTable']['Properties'][0]
|
||||
0
jarvis/api/database/__init__.py
Normal file
0
jarvis/api/database/__init__.py
Normal file
44
jarvis/api/database/database.py
Normal file
44
jarvis/api/database/database.py
Normal file
@@ -0,0 +1,44 @@
|
||||
import datetime
|
||||
from typing import List
|
||||
from fastapi import APIRouter, HTTPException
|
||||
from pydantic import BaseModel
|
||||
import sqlite3
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
class SQLRequest(BaseModel):
|
||||
queries: List[str]
|
||||
|
||||
|
||||
def execute_sql(queries: List[str]):
|
||||
conn = sqlite3.connect('./tasks/travel/database/travel.db')
|
||||
cursor = conn.cursor()
|
||||
|
||||
results = []
|
||||
for query in queries:
|
||||
try:
|
||||
cursor.execute(query)
|
||||
results.append({
|
||||
"query": query,
|
||||
"result": cursor.fetchall(),
|
||||
"error": ""
|
||||
})
|
||||
except Exception as e:
|
||||
results.append({
|
||||
"query": query,
|
||||
"result": "",
|
||||
"error": str(e)
|
||||
})
|
||||
|
||||
# Commit changes and close the connection to the database
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
return results
|
||||
|
||||
|
||||
@router.post("/tools/database")
|
||||
async def execute_sqlite(req: SQLRequest):
|
||||
print(f"{datetime.datetime.now()}:{req}")
|
||||
return execute_sql(req.queries)
|
||||
42
jarvis/api/database/test.py
Normal file
42
jarvis/api/database/test.py
Normal file
@@ -0,0 +1,42 @@
|
||||
import requests
|
||||
import json
|
||||
|
||||
# 你的API的URL
|
||||
url = "http://localhost:8079/tools/database"
|
||||
|
||||
# 准备的SQL查询
|
||||
queries = {
|
||||
"queries": [
|
||||
'''SELECT * FROM railway
|
||||
WHERE origin = 'Beijing'
|
||||
AND destination = 'Shanghai'
|
||||
AND DATE(departure_time) = '2023-07-08'
|
||||
ORDER BY departure_time;'''
|
||||
]
|
||||
}
|
||||
# queries = {"queries":["SELECT * FROM railway\nWHERE origin = 'Shanghai'\n AND destination = 'Hangzhou'\n AND DATE(departure_time) = '2023-07-04';"]
|
||||
# }
|
||||
|
||||
# 发送POST请求
|
||||
response = requests.post(url, json=queries)
|
||||
|
||||
# 打印返回的结果
|
||||
print(json.dumps(response.json(), indent=4))
|
||||
|
||||
|
||||
def query_database(query):
|
||||
try:
|
||||
response = requests.post(
|
||||
"http://localhost:8079/tools/database",
|
||||
json={'queries': query}
|
||||
).json()
|
||||
return json.dumps(response, indent=4)
|
||||
except Exception as e:
|
||||
print(f'run error{e}')
|
||||
|
||||
|
||||
query = [
|
||||
"SELECT * FROM railway\nWHERE origin = 'Shanghai'\n AND destination = 'Beijing'\n AND DATE(departure_time) = '2023-07-01';",
|
||||
"SELECT * FROM railway\nWHERE origin = 'Beijing'\n AND destination = 'Hangzhou'\n AND DATE(departure_time) = '2023-07-04';",
|
||||
"SELECT * FROM railway\nWHERE origin = 'Hangzhou'\n AND destination = 'Shanghai'\n AND DATE(departure_time) = '2023-07-07';"]
|
||||
print(query_database(query))
|
||||
0
jarvis/api/gmail/__init__.py
Normal file
0
jarvis/api/gmail/__init__.py
Normal file
86
jarvis/api/gmail/gmail.py
Normal file
86
jarvis/api/gmail/gmail.py
Normal file
@@ -0,0 +1,86 @@
|
||||
import os
|
||||
from google.oauth2.credentials import Credentials
|
||||
from google_auth_oauthlib.flow import InstalledAppFlow
|
||||
from google.auth.transport.requests import Request as google_request
|
||||
from googleapiclient.discovery import build
|
||||
import base64
|
||||
from email.mime.text import MIMEText
|
||||
import pickle
|
||||
|
||||
SCOPES = ['https://www.googleapis.com/auth/gmail.send', 'https://www.googleapis.com/auth/gmail.readonly',
|
||||
'https://www.googleapis.com/auth/calendar']
|
||||
|
||||
|
||||
def get_service():
|
||||
creds = None
|
||||
# 尝试从 "token.pickle" 文件中加载凭据
|
||||
if os.path.exists('token.pickle'):
|
||||
with open('token.pickle', 'rb') as token:
|
||||
creds = pickle.load(token)
|
||||
if creds and not creds.valid:
|
||||
if creds.expired and creds.refresh_token:
|
||||
creds.refresh(google_request())
|
||||
else:
|
||||
flow = InstalledAppFlow.from_client_secrets_file(
|
||||
'./.auth/calendar.json', SCOPES)
|
||||
creds = flow.run_local_server(port=0)
|
||||
service = build('gmail', 'v1', credentials=creds)
|
||||
return service
|
||||
|
||||
|
||||
def send_email(service, from_email, to_email, subject, content):
|
||||
message = MIMEText(content)
|
||||
message['to'] = to_email
|
||||
message['from'] = from_email
|
||||
message['subject'] = subject
|
||||
raw_message = base64.urlsafe_b64encode(message.as_string().encode("utf-8"))
|
||||
message = {'raw': raw_message.decode("utf-8")}
|
||||
message = (service.users().messages().send(userId='me', body=message).execute())
|
||||
|
||||
|
||||
from fastapi import APIRouter
|
||||
import json
|
||||
import base64
|
||||
from email.mime.text import MIMEText
|
||||
from pydantic import BaseModel
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
class EmailSchema(BaseModel):
|
||||
from_email: str
|
||||
to_email: str
|
||||
subject: str
|
||||
content: str
|
||||
|
||||
|
||||
@router.post("/gmail/send")
|
||||
def send_test_email(email: EmailSchema):
|
||||
try:
|
||||
service = get_service()
|
||||
send_email(service, email.from_email, email.to_email, email.subject, email.content) # 注意这里从email对象中取字段
|
||||
return {"result": "Email sent successfully", "error": None}
|
||||
except Exception as e:
|
||||
return {"result": None, "error": str(e)}
|
||||
|
||||
|
||||
# token.pickle文件包含了与特定Gmail账户关联的访问令牌
|
||||
@router.get("/gmail/list")
|
||||
def list_recent_emails():
|
||||
try:
|
||||
service = get_service()
|
||||
results = service.users().messages().list(userId='me', labelIds=['INBOX'], maxResults=10).execute()
|
||||
messages = results.get('messages', [])
|
||||
emails = []
|
||||
for message in messages:
|
||||
msg = service.users().messages().get(userId='me', id=message['id']).execute()
|
||||
email_data = msg['payload']['headers']
|
||||
for values in email_data:
|
||||
name = values['name']
|
||||
if name == 'From':
|
||||
from_name = values['value']
|
||||
subject = msg['snippet']
|
||||
emails.append({"from": from_name, "subject": subject})
|
||||
return {"emails": emails, "error": None}
|
||||
except Exception as e:
|
||||
return {"emails": None, "error": str(e)}
|
||||
38
jarvis/api/gmail/test.py
Normal file
38
jarvis/api/gmail/test.py
Normal file
@@ -0,0 +1,38 @@
|
||||
import os
|
||||
|
||||
import requests
|
||||
import json
|
||||
|
||||
# 基础URL
|
||||
BASE_URL = "http://127.0.0.1:8079"
|
||||
|
||||
# 测试邮件发送API
|
||||
def test_send_email():
|
||||
print("Testing: Send Email API")
|
||||
|
||||
data = {
|
||||
"from_email": "wyx7653@gmail.com",
|
||||
"to_email": "2115492705@qq.com",
|
||||
"subject": "Test Subject",
|
||||
"content": "This is a test email."
|
||||
}
|
||||
|
||||
response = requests.post(f"{BASE_URL}/gmail/send", json=data)
|
||||
if response.status_code == 200:
|
||||
print(f"Success: {response.json()}")
|
||||
else:
|
||||
print(f"Failure: {response.json()}")
|
||||
|
||||
# 测试获取最近邮件列表API
|
||||
def test_list_recent_emails():
|
||||
print("Testing: List Recent Emails API")
|
||||
|
||||
response = requests.get(f"{BASE_URL}/gmail/list")
|
||||
if response.status_code == 200:
|
||||
print(f"Success: {response.json()}")
|
||||
else:
|
||||
print(f"Failure: {response.json()}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_send_email()
|
||||
test_list_recent_emails()
|
||||
0
jarvis/api/google_calendar/__init__.py
Normal file
0
jarvis/api/google_calendar/__init__.py
Normal file
57
jarvis/api/google_calendar/calendar_service.py
Normal file
57
jarvis/api/google_calendar/calendar_service.py
Normal file
@@ -0,0 +1,57 @@
|
||||
# 开启Google Calendar API并下载凭据: 访问Google Cloud Console,创建一个新的项目并启用Google Calendar API。下载生成的credentials.json文件。
|
||||
import os
|
||||
|
||||
from fastapi import APIRouter
|
||||
from pydantic import BaseModel, Field
|
||||
from google_auth_oauthlib.flow import InstalledAppFlow
|
||||
from google.auth.transport.requests import Request as google_request
|
||||
from googleapiclient.discovery import build
|
||||
import pickle
|
||||
|
||||
# 如果修改了SCOPES,请删除文件token.pickle。
|
||||
SCOPES = ['https://www.googleapis.com/auth/gmail.send','https://www.googleapis.com/auth/gmail.readonly','https://www.googleapis.com/auth/calendar']
|
||||
|
||||
|
||||
|
||||
def get_service():
|
||||
creds = None
|
||||
# 尝试从 "token.pickle" 文件中加载凭据
|
||||
if os.path.exists('token.pickle'):
|
||||
with open('token.pickle', 'rb') as token:
|
||||
creds = pickle.load(token)
|
||||
|
||||
# 如果凭据无效,重新获取
|
||||
if not creds or not creds.valid:
|
||||
if creds and creds.expired and creds.refresh_token:
|
||||
creds.refresh(google_request())
|
||||
else:
|
||||
flow = InstalledAppFlow.from_client_secrets_file(
|
||||
'./.auth/calendar.json', SCOPES)
|
||||
creds = flow.run_local_server(port=0)
|
||||
|
||||
# 保存新的凭据到 "token.pickle" 文件
|
||||
with open('token.pickle', 'wb') as token:
|
||||
pickle.dump(creds, token)
|
||||
|
||||
service = build('calendar', 'v3', credentials=creds)
|
||||
return service
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
class CalendarEvent(BaseModel):
|
||||
summary: str
|
||||
location: str
|
||||
description: str
|
||||
start: dict = Field(..., example={"dateTime": "2023-07-31T15:00:00", "timeZone": "Asia/Shanghai"})
|
||||
end: dict = Field(..., example={"dateTime": "2023-07-31T16:00:00", "timeZone": "Asia/Shanghai"})
|
||||
|
||||
|
||||
@router.post("/calendar/insert_event")
|
||||
def insert_event(event: CalendarEvent):
|
||||
try:
|
||||
# 这里你可以调用Google Calendar API
|
||||
service = get_service() # 从你原来的代码获取service
|
||||
inserted_event = service.events().insert(calendarId='primary', body=event.dict()).execute()
|
||||
return {"result": f'Event created: {inserted_event["htmlLink"]}', "error": None}
|
||||
except Exception as e:
|
||||
return {"result": None, "error": str(e)}
|
||||
25
jarvis/api/google_calendar/test.py
Normal file
25
jarvis/api/google_calendar/test.py
Normal file
@@ -0,0 +1,25 @@
|
||||
import requests
|
||||
import json
|
||||
|
||||
# 用于测试的日历事件
|
||||
test_event = {
|
||||
"summary": "NLUI会议",
|
||||
"location": "上海",
|
||||
"description": "这是一个关于NLUI的会议",
|
||||
"start": {
|
||||
"dateTime": "2023-08-28T10:30:00",
|
||||
"timeZone": "Asia/Shanghai"
|
||||
},
|
||||
"end": {
|
||||
"dateTime": "2023-08-28T11:30:00", # 假设会议时长为1小时
|
||||
"timeZone": "Asia/Shanghai"
|
||||
}
|
||||
}
|
||||
|
||||
# 向API发送请求
|
||||
response = requests.post("http://127.0.0.1:8079/calendar/insert_event", json=test_event)
|
||||
|
||||
# 解析响应
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
print(data)
|
||||
0
jarvis/api/ppt/__init__.py
Normal file
0
jarvis/api/ppt/__init__.py
Normal file
115
jarvis/api/ppt/ppt.py
Normal file
115
jarvis/api/ppt/ppt.py
Normal file
@@ -0,0 +1,115 @@
|
||||
from fastapi import APIRouter, Depends
|
||||
from pydantic import BaseModel
|
||||
from pptx import Presentation
|
||||
import os
|
||||
import time
|
||||
import requests
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
CWD = os.getcwd() # path of current working directory
|
||||
LIB_DIR = os.path.dirname(__file__) # path of library
|
||||
TEMPLATE_DIR = os.path.join(LIB_DIR, "templates") # path of templates
|
||||
CACHE_DIR = os.path.join(CWD, "cache") # path of cache_dir
|
||||
IMAGE_BED_PATTERN = 'https://source.unsplash.com/featured/?{}' # url pattern for image bed
|
||||
|
||||
if not os.path.exists(CACHE_DIR):
|
||||
os.makedirs(CACHE_DIR)
|
||||
|
||||
ppt_file = None # a pointer to the powerpoint object
|
||||
|
||||
|
||||
class CreateFileModel(BaseModel):
|
||||
theme: str
|
||||
|
||||
|
||||
class GetImageModel(BaseModel):
|
||||
keywords: str
|
||||
|
||||
|
||||
class AddFirstPageModel(BaseModel):
|
||||
title: str
|
||||
subtitle: str
|
||||
|
||||
|
||||
class AddTextPageModel(BaseModel):
|
||||
title: str
|
||||
bullet_items: str
|
||||
|
||||
|
||||
class AddTextImagePageModel(BaseModel):
|
||||
title: str
|
||||
bullet_items: str
|
||||
image: str
|
||||
|
||||
|
||||
@router.post("/tools/ppt/create_file")
|
||||
async def create_file(item: CreateFileModel):
|
||||
global ppt_file
|
||||
ppt_file = Presentation(os.path.join(TEMPLATE_DIR, f"{item.theme}.pptx"))
|
||||
return "created a ppt file."
|
||||
|
||||
|
||||
@router.post("/tools/ppt/get_image")
|
||||
async def get_image(item: GetImageModel):
|
||||
picture_url = IMAGE_BED_PATTERN.format(item.keywords)
|
||||
response = requests.get(picture_url)
|
||||
img_local_path = os.path.join(CACHE_DIR, f"{time.time()}.jpg")
|
||||
with open(img_local_path, 'wb') as f:
|
||||
f.write(response.content)
|
||||
return img_local_path
|
||||
|
||||
|
||||
@router.post("/tools/ppt/add_first_page")
|
||||
async def add_first_page(item: AddFirstPageModel):
|
||||
global ppt_file
|
||||
slide = ppt_file.slides.add_slide(ppt_file.slide_layouts[0]) # layout for first page (title and subtitle only)
|
||||
title_shape = slide.shapes.title
|
||||
subtitle_shape = slide.placeholders[1]
|
||||
title_shape.text = item.title
|
||||
subtitle_shape.text = item.subtitle
|
||||
return "added first page."
|
||||
|
||||
|
||||
@router.post("/tools/ppt/add_text_page")
|
||||
async def add_text_page(item: AddTextPageModel):
|
||||
global ppt_file
|
||||
slide = ppt_file.slides.add_slide(ppt_file.slide_layouts[1])
|
||||
title_shape = slide.shapes.title
|
||||
body_shape = slide.placeholders[1]
|
||||
title_shape.text = item.title
|
||||
tf = body_shape.text_frame
|
||||
bullet_items = item.bullet_items.split("[SPAN]")
|
||||
for bullet_item in bullet_items:
|
||||
bullet_item_strip = bullet_item.strip()
|
||||
p = tf.add_paragraph()
|
||||
p.text = bullet_item_strip
|
||||
p.level = 1
|
||||
return "added text page."
|
||||
|
||||
|
||||
@router.post("/tools/ppt/add_text_image_page")
|
||||
async def add_text_image_page(item: AddTextImagePageModel):
|
||||
global ppt_file
|
||||
slide = ppt_file.slides.add_slide(ppt_file.slide_layouts[3])
|
||||
title_shape = slide.shapes.title
|
||||
title_shape.text = item.title
|
||||
body_shape = slide.placeholders[1]
|
||||
tf = body_shape.text_frame
|
||||
bullet_items = item.bullet_items.split("[SPAN]")
|
||||
for bullet_item in bullet_items:
|
||||
bullet_item_strip = bullet_item.strip()
|
||||
p = tf.add_paragraph()
|
||||
p.text = bullet_item_strip
|
||||
p.level = 1
|
||||
image_shape = slide.placeholders[2]
|
||||
slide.shapes.add_picture(item.image, image_shape.left, image_shape.top, image_shape.width, image_shape.height)
|
||||
return "added text and image page."
|
||||
|
||||
|
||||
@router.get("/tools/ppt/submit_file")
|
||||
async def submit_file():
|
||||
global ppt_file
|
||||
file_path = os.path.join(CACHE_DIR, f"{time.time()}.pptx")
|
||||
ppt_file.save(file_path)
|
||||
return f"submitted. view ppt at {file_path}"
|
||||
BIN
jarvis/api/ppt/templates/flat.pptx
Normal file
BIN
jarvis/api/ppt/templates/flat.pptx
Normal file
Binary file not shown.
BIN
jarvis/api/ppt/templates/green.pptx
Normal file
BIN
jarvis/api/ppt/templates/green.pptx
Normal file
Binary file not shown.
BIN
jarvis/api/ppt/templates/orange.pptx
Normal file
BIN
jarvis/api/ppt/templates/orange.pptx
Normal file
Binary file not shown.
BIN
jarvis/api/ppt/templates/tech.pptx
Normal file
BIN
jarvis/api/ppt/templates/tech.pptx
Normal file
Binary file not shown.
BIN
jarvis/api/ppt/templates/wooden.pptx
Normal file
BIN
jarvis/api/ppt/templates/wooden.pptx
Normal file
Binary file not shown.
16
jarvis/api/ppt/test.py
Normal file
16
jarvis/api/ppt/test.py
Normal file
@@ -0,0 +1,16 @@
|
||||
import requests
|
||||
|
||||
ppt_url='http://localhost:8079/tools/ppt'
|
||||
|
||||
#创建文件
|
||||
requests.post(f'{ppt_url}/create_file', json={"theme": "tech"})
|
||||
#获取图片
|
||||
response = requests.post(f'{ppt_url}/get_image', json={"keywords": "programming"})
|
||||
image_path = response.json()
|
||||
#加一页
|
||||
requests.post(f'{ppt_url}/add_first_page', json={"title": "About Me", "subtitle": "A brief introduction"})
|
||||
requests.post(f'{ppt_url}/add_text_page', json={"title": "Education", "bullet_items": "Bachelor's Degree in Computer Science[SPAN]Master's Degree in Data Science"})
|
||||
requests.post(f'{ppt_url}/add_text_image_page', json={"title": "Skills", "bullet_items": "Programming[SPAN]Data Analysis[SPAN]Machine Learning", "image": image_path})
|
||||
response = requests.get(f'{ppt_url}/submit_file')
|
||||
file_path = response.json()
|
||||
print(file_path)
|
||||
0
jarvis/api/python/__init__.py
Normal file
0
jarvis/api/python/__init__.py
Normal file
108
jarvis/api/python/interpreter.py
Normal file
108
jarvis/api/python/interpreter.py
Normal file
@@ -0,0 +1,108 @@
|
||||
import ast
|
||||
import os
|
||||
import asyncio
|
||||
import subprocess
|
||||
|
||||
import astor
|
||||
from fastapi import APIRouter, HTTPException
|
||||
from pydantic import BaseModel
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
class Item(BaseModel):
|
||||
code: str
|
||||
|
||||
|
||||
def modify_code_to_print_last_expr(code: str):
|
||||
# Parse the code using AST
|
||||
tree = ast.parse(code, mode='exec')
|
||||
|
||||
# Check if the last node is an expression and not a print statement
|
||||
last_node = tree.body[-1]
|
||||
if isinstance(last_node, ast.Expr) and not (
|
||||
isinstance(last_node.value, ast.Call) and getattr(last_node.value.func, 'id', None) == 'print'):
|
||||
# Create a new print node
|
||||
print_node = ast.Expr(
|
||||
value=ast.Call(func=ast.Name(id='print', ctx=ast.Load()), args=[last_node.value], keywords=[]))
|
||||
# Copy line number and column offset from the last expression
|
||||
print_node.lineno = last_node.lineno
|
||||
print_node.col_offset = last_node.col_offset
|
||||
# Replace the last expression with the print statement
|
||||
tree.body[-1] = print_node
|
||||
|
||||
# Use astor to convert the modified AST back to source code
|
||||
modified_code = astor.to_source(tree)
|
||||
return modified_code
|
||||
|
||||
|
||||
async def run_code(code: str):
|
||||
|
||||
try:
|
||||
code = modify_code_to_print_last_expr(code)
|
||||
# Write the code to a file
|
||||
with open("code.py", "w") as f:
|
||||
f.write(code)
|
||||
with open("code_temp.py", "w") as f:
|
||||
f.write(code)
|
||||
# Run the file with a timeout of 3 seconds
|
||||
process = await asyncio.create_subprocess_shell(
|
||||
"python code.py",
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE
|
||||
)
|
||||
stdout, stderr = await asyncio.wait_for(process.communicate(), timeout=3)
|
||||
|
||||
# Decode the stdout and stderr
|
||||
result = stdout.decode("utf-8")
|
||||
error = stderr.decode("utf-8")
|
||||
|
||||
return {"result": result, "error": error}
|
||||
except asyncio.TimeoutError:
|
||||
process.terminate()
|
||||
await process.wait()
|
||||
return {"result": "", "error": "Code execution timed out"}
|
||||
except Exception as e:
|
||||
return {"result": "", "error": str(e)}
|
||||
finally:
|
||||
# Delete the code file
|
||||
if os.path.exists("code.py"):
|
||||
os.remove("code.py")
|
||||
|
||||
|
||||
@router.post("/tools/python")
|
||||
async def execute_python(item: Item):
|
||||
result = await run_code(item.code)
|
||||
return result
|
||||
|
||||
# import io
|
||||
# import traceback
|
||||
# from contextlib import redirect_stdout
|
||||
# from fastapi import APIRouter, HTTPException
|
||||
# from pydantic import BaseModel
|
||||
# from concurrent.futures import ThreadPoolExecutor, TimeoutError
|
||||
#
|
||||
# router = APIRouter()
|
||||
#
|
||||
# executor = ThreadPoolExecutor(max_workers=1)
|
||||
#
|
||||
# class Item(BaseModel):
|
||||
# code: str
|
||||
#
|
||||
# def execute_code(code):
|
||||
# f = io.StringIO()
|
||||
# with redirect_stdout(f):
|
||||
# try:
|
||||
# exec(code)
|
||||
# return {"result": f.getvalue(), "error": None}
|
||||
# except Exception as e:
|
||||
# return {"result": f.getvalue(), "error": traceback.format_exc().split('exec(code)\n ')[-1]}
|
||||
#
|
||||
# @router.post("/tools/python")
|
||||
# async def execute_python(item: Item):
|
||||
# future = executor.submit(execute_code, item.code)
|
||||
# try:
|
||||
# result = future.result(timeout=3) # Wait for the result or timeout after 3 seconds
|
||||
# except TimeoutError:
|
||||
# return {"result": None, "error": "TimeoutError"}
|
||||
# return result
|
||||
1
jarvis/api/python/temp.py
Normal file
1
jarvis/api/python/temp.py
Normal file
@@ -0,0 +1 @@
|
||||
print('hello')
|
||||
14
jarvis/api/python/test.py
Normal file
14
jarvis/api/python/test.py
Normal file
@@ -0,0 +1,14 @@
|
||||
import requests
|
||||
import json
|
||||
|
||||
code = """
|
||||
import heapq as hq\r\nfrom collections import Counter\r\n\r\ndef func(lists, k):\r\n nums = []\r\n for lst in lists:\r\n nums.extend(lst)\r\n count = Counter(nums)\r\n top_k = hq.nlargest(k, count, key=count.get)\r\n return top_k\nassert func([[1, 2, 6], [1, 3, 4, 5, 7, 8], [1, 3, 5, 6, 8, 9], [2, 5, 7, 11], [1, 4, 7, 8, 12]],3)==[5, 7, 1]\nassert func([[1, 2, 6], [1, 3, 4, 5, 7, 8], [1, 3, 5, 6, 8, 9], [2, 5, 7, 11], [1, 4, 7, 8, 12]],1)==[1]\nassert func([[1, 2, 6], [1, 3, 4, 5, 7, 8], [1, 3, 5, 6, 8, 9], [2, 5, 7, 11], [1, 4, 7, 8, 12]],5)==[6, 5, 7, 8, 1]\n
|
||||
"""
|
||||
code="""
|
||||
print('hello world')"""
|
||||
response = requests.post(
|
||||
'http://127.0.0.1:8079/tools/python',
|
||||
json={'code': code}
|
||||
)
|
||||
|
||||
print(response.json())
|
||||
15
jarvis/api/python/test2.py
Normal file
15
jarvis/api/python/test2.py
Normal file
@@ -0,0 +1,15 @@
|
||||
import requests
|
||||
import json
|
||||
|
||||
code = """
|
||||
import heapq as hq\r\nfrom collections import Counter\r\n\r\ndef func(lists, k):\r\n nums = []\r\n for lst in lists:\r\n nums.extend(lst)\r\n count = Counter(nums)\r\n top_k = hq.nlargest(k, count, key=count.get)\r\n return top_k\nassert func([[1, 2, 6], [1, 3, 4, 5, 7, 8], [1, 3, 5, 6, 8, 9], [2, 5, 7, 11], [1, 4, 7, 8, 12]],3)==[5, 7, 1]\nassert func([[1, 2, 6], [1, 3, 4, 5, 7, 8], [1, 3, 5, 6, 8, 9], [2, 5, 7, 11], [1, 4, 7, 8, 12]],1)==[1]\nassert func([[1, 2, 6], [1, 3, 4, 5, 7, 8], [1, 3, 5, 6, 8, 9], [2, 5, 7, 11], [1, 4, 7, 8, 12]],5)==[6, 5, 7, 8, 1]\n
|
||||
"""
|
||||
code="""
|
||||
abcde
|
||||
fs"""
|
||||
response = requests.post(
|
||||
'http://127.0.0.1:8079/tools/python',
|
||||
json={'code': code}
|
||||
)
|
||||
|
||||
print(response.json())
|
||||
0
jarvis/api/shell/__init__.py
Normal file
0
jarvis/api/shell/__init__.py
Normal file
17
jarvis/api/shell/shell.py
Normal file
17
jarvis/api/shell/shell.py
Normal file
@@ -0,0 +1,17 @@
|
||||
from fastapi import APIRouter
|
||||
from pydantic import BaseModel
|
||||
import subprocess
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
class ShellCommandModel(BaseModel):
|
||||
command: str
|
||||
|
||||
class ShellCommandResultModel(BaseModel):
|
||||
stdout: str
|
||||
stderr: str
|
||||
|
||||
@router.post("/tools/shell", response_model=ShellCommandResultModel)
|
||||
async def execute_shell_command(command: ShellCommandModel):
|
||||
result = subprocess.run(command.command, capture_output=True, shell=True, text=True)
|
||||
return ShellCommandResultModel(stdout=result.stdout, stderr=result.stderr)
|
||||
19
jarvis/api/shell/test.py
Normal file
19
jarvis/api/shell/test.py
Normal file
@@ -0,0 +1,19 @@
|
||||
import requests
|
||||
import json
|
||||
|
||||
base_url = 'http://localhost:8079'
|
||||
|
||||
def run_shell_command(command):
|
||||
response = requests.post(f'{base_url}/tools/shell', data=json.dumps({"command": command}), headers={'Content-Type': 'application/json'})
|
||||
if response.status_code == 200:
|
||||
print("Command executed successfully")
|
||||
print("STDOUT: ", response.json()['stdout'])
|
||||
print("STDERR: ", response.json()['stderr'])
|
||||
else:
|
||||
print("Error occurred while executing the command")
|
||||
|
||||
# Create the file in /root directory
|
||||
run_shell_command("echo 'This is a test file.' > /root/test.txt")
|
||||
|
||||
# Copy the file to the current directory
|
||||
run_shell_command("cp /root/test.txt ./test2.txt")
|
||||
0
jarvis/api/sympy/__init__.py
Normal file
0
jarvis/api/sympy/__init__.py
Normal file
13
jarvis/api/sympy/test.py
Normal file
13
jarvis/api/sympy/test.py
Normal file
@@ -0,0 +1,13 @@
|
||||
from sympy import symbols, Eq, solve
|
||||
|
||||
x, y = symbols('x y')
|
||||
|
||||
# 设方程组为:
|
||||
# 3x + 2y = 2
|
||||
# x + 2y = 0
|
||||
eq1 = Eq(3*x + 2*y, 2)
|
||||
eq2 = Eq(x + 2*y, 0)
|
||||
|
||||
# 使用 solve 解方程组
|
||||
sol = solve((eq1,eq2), (x, y))
|
||||
print(sol)
|
||||
0
jarvis/api/translate/__init__.py
Normal file
0
jarvis/api/translate/__init__.py
Normal file
25
jarvis/api/translate/translate.py
Normal file
25
jarvis/api/translate/translate.py
Normal file
@@ -0,0 +1,25 @@
|
||||
from fastapi import APIRouter
|
||||
from pydantic import BaseModel
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
class TranslateRequest(BaseModel):
|
||||
text: str
|
||||
src_language: str
|
||||
dest_language: str
|
||||
|
||||
class TranslateResponse(BaseModel):
|
||||
translated_text: str
|
||||
|
||||
def translate_text(text: str, src_language: str, dest_language: str) -> str:
|
||||
"""
|
||||
Translates the text from source language to destination language.
|
||||
This function is just a placeholder. You should implement the actual translation here.
|
||||
"""
|
||||
# TODO: implement the translation
|
||||
return text
|
||||
|
||||
@router.post("/tools/translate", response_model=TranslateResponse)
|
||||
async def translate(request: TranslateRequest) -> TranslateResponse:
|
||||
translated_text = translate_text(request.text, request.src_language, request.dest_language)
|
||||
return TranslateResponse(translated_text=translated_text)
|
||||
0
jarvis/api/weather/__init__.py
Normal file
0
jarvis/api/weather/__init__.py
Normal file
23
jarvis/api/weather/test.py
Normal file
23
jarvis/api/weather/test.py
Normal file
@@ -0,0 +1,23 @@
|
||||
# test_weather_api.py
|
||||
|
||||
import requests
|
||||
|
||||
def test_query_weather():
|
||||
base_url = "http://127.0.0.1:8079"
|
||||
date = "2023-07-01"
|
||||
city = "Beijing"
|
||||
|
||||
# 发送GET请求到/weather/query端点
|
||||
response = requests.get(f"{base_url}/weather/query", params={"date": date, "city": city})
|
||||
|
||||
# 检查响应是否成功
|
||||
if response.status_code == 200:
|
||||
print("Test Passed")
|
||||
print("Response JSON:", response.json())
|
||||
else:
|
||||
print("Test Failed")
|
||||
print("Response Status Code:", response.status_code)
|
||||
print("Response JSON:", response.json())
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_query_weather()
|
||||
24
jarvis/api/weather/weather.py
Normal file
24
jarvis/api/weather/weather.py
Normal file
@@ -0,0 +1,24 @@
|
||||
# api/weather/weather.py
|
||||
from fastapi import APIRouter, HTTPException, Query
|
||||
import sqlite3
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
@router.get("/weather/query") # 注意这里改为GET请求
|
||||
def query_weather(date: str, city: str): # 使用Query参数
|
||||
try:
|
||||
conn = sqlite3.connect('./database/weather.db')
|
||||
c = conn.cursor()
|
||||
c.execute("SELECT max_temp, min_temp, weather FROM weather WHERE city=? AND date=?", (city, date))
|
||||
row = c.fetchone()
|
||||
conn.close()
|
||||
|
||||
if row:
|
||||
result=f'{date}, {city}: {row[2]}, {row[1]}-{row[0]} ℃'
|
||||
return {"result": str(result), "error": None}
|
||||
else:
|
||||
{"result": '', "error": 'data not found'}
|
||||
|
||||
except Exception as e:
|
||||
print(e)
|
||||
return {"result": '', "error": 'not found'}
|
||||
0
jarvis/api/wolfram_alpha/__init__.py
Normal file
0
jarvis/api/wolfram_alpha/__init__.py
Normal file
21
jarvis/api/wolfram_alpha/test.py
Normal file
21
jarvis/api/wolfram_alpha/test.py
Normal file
@@ -0,0 +1,21 @@
|
||||
import requests
|
||||
import json
|
||||
|
||||
# API endpoint
|
||||
url = "http://127.0.0.1:8079/tools/wolframalpha"
|
||||
|
||||
# Headers
|
||||
headers = {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
|
||||
# Data
|
||||
data = {
|
||||
"query": "5+6"
|
||||
}
|
||||
|
||||
# Send the request
|
||||
response = requests.post(url, headers=headers, data=json.dumps(data))
|
||||
|
||||
# Print the response
|
||||
print(response.json())
|
||||
24
jarvis/api/wolfram_alpha/wolfram_alpha.py
Normal file
24
jarvis/api/wolfram_alpha/wolfram_alpha.py
Normal file
@@ -0,0 +1,24 @@
|
||||
from fastapi import APIRouter
|
||||
import wolframalpha
|
||||
from pydantic import BaseModel
|
||||
from typing import Optional
|
||||
|
||||
class QueryItem(BaseModel):
|
||||
query: str
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
app_id = "XRY28U-7PVE2LRH7H" # Replace with your app id
|
||||
client = wolframalpha.Client(app_id)
|
||||
|
||||
@router.post("/tools/wolframalpha")
|
||||
async def wolframalpha_query(item: QueryItem):
|
||||
res = client.query(item.query)
|
||||
|
||||
# Handle the query result
|
||||
if res['@success'] == 'false':
|
||||
return {"result": "Query failed"}
|
||||
else:
|
||||
# Return the first result text
|
||||
result = next(res.results).text
|
||||
return {"result": result}
|
||||
@@ -18,4 +18,268 @@ please using the following format to reply:
|
||||
{response}respond to user request based on thought
|
||||
```
|
||||
Now you are ready to take questions, requests from users.
|
||||
"""
|
||||
"""
|
||||
|
||||
# Travel
|
||||
TRAVEL_ORIGINAL_DOCUMENT = """<action>execute_sql(statement:string)</action>
|
||||
You can use the action ’execute_sql’ to get some information from the database.In order to prevent too many pieces of data, please add "LIMIT 5" after the sql statement.
|
||||
|
||||
Tables in the database are as follows.
|
||||
Table railway:
|
||||
CREATE TABLE railway(
|
||||
number TEXT, /*ticket number*/
|
||||
origin TEXT,
|
||||
destination TEXT,
|
||||
departure_time DATETIME,
|
||||
arrival_time DATETIME,
|
||||
duration INTEGER, /*indicates how many minutes are spent on the train*/
|
||||
price REAL
|
||||
)
|
||||
From table railway, you can filter the items according to the origin, destination, and departure date, and then plan according to the obtained information. Don’t use duration as a filtering condition.
|
||||
If you buy a ticket, please point out the number of it.
|
||||
|
||||
Table place:
|
||||
CREATE TABLE place(
|
||||
name TEXT,
|
||||
city TEXT,
|
||||
type TEXT,
|
||||
opening_hours_begin INTEGER,
|
||||
opening_hours_end INTEGER,
|
||||
price REAL,
|
||||
visit_hours INTEGER
|
||||
)
|
||||
From table place, you can filter the items according to the city to know some information of places in this city.
|
||||
|
||||
Table in_city_transport:
|
||||
CREATE TABLE in_city_transport(
|
||||
origin TEXT,
|
||||
destination TEXT,
|
||||
duration INTEGER, /*indicates how many minutes are spent in traffic*/
|
||||
city TEXT
|
||||
)
|
||||
|
||||
From table in_city_transport, you can know how long you may spend from origin to destination.
|
||||
Before visiting a spot, you must spend time going to this spot from the hotel or another spot.
|
||||
|
||||
Be careful to set conditions, otherwise too many items will be retrieved from the database.
|
||||
Usage examples:
|
||||
<action>execute_sql('''
|
||||
SELECT * FROM place
|
||||
WHERE city = 'Beijing';''')</action>
|
||||
<action>execute_sql('''
|
||||
SELECT origin, destination, duration FROM in_city_transport
|
||||
WHERE city = 'Hangzhou' AND
|
||||
(origin IN ('West Lake', 'Lingyin Temple', 'Hefang Street', 'Quaint Water Towns') AND
|
||||
destination IN ('West Lake', 'Lingyin Temple', 'Hefang Street', 'Quaint Water Towns'));''')</action>
|
||||
<action>execute_sql('''
|
||||
SELECT * FROM railway
|
||||
WHERE origin = 'Beijing'
|
||||
AND destination = 'Shanghai'
|
||||
AND DATE(departure_time) >= '2023-07-25'
|
||||
LIMIT 5;''')</action>.
|
||||
|
||||
|
||||
<action>execute_python(code:string)</action>
|
||||
You can use the action ‘execute_python()’ to assist your planning. You must use print() in the python code to get what you want to know. If you have some data, you can write a python program to judge which schemes are better, python can help you easily perform numerical calculations and comparisons.
|
||||
You can use dynamic programming, greedy algorithm or direct traversal to get the better plan.
|
||||
The code must be complete and directly executable. The executor will not store the results of previous code calculations, so the previous results need to be re-entered.
|
||||
If you want to use execute_sql in execute_python, add 'from utils.travel import execute_sql' in python code.
|
||||
The python code should be surrounded by \"\"\" and \"\"\".
|
||||
e.g.
|
||||
<action>execute_python(\"\"\"
|
||||
price=[540, 300, 210]
|
||||
print(f 'The total cost is {{sum(price)}}')
|
||||
\"\"\")</action>
|
||||
"""
|
||||
|
||||
|
||||
TRAVEL_SYSTEM_PROMPT = f'''You are an autonomous intelligent agent tasked with making travel plans for Bob. To be successful, it is very important to follow the following rules:
|
||||
1. You should only issue one action at a time.
|
||||
2. You should reason step by step and then issue the next action.
|
||||
3. Your response should be formatted as follows:
|
||||
THOUGHT: the thought process to achieve the goal, including the subtask to be handled.
|
||||
ACTION: the action you call to get information or submit the task.
|
||||
|
||||
EXTERNAL RESOURCES:
|
||||
1. A database containing information about train tickets, attractions, and city transportation.
|
||||
2. A python notebook to execute python code for numerical operations and planning.
|
||||
|
||||
TASK DESCRIPTION
|
||||
You need to make a travel plan based on the given requirements, taking into account transportation between cities and daily schedules.
|
||||
The final plan may include or be part of the following:
|
||||
1.go_to_place(origin:str,destination:str,departure_time,arrival_time): go to destination from origin. The origin and destination should be the name of a hotel or a spot instead of a city.
|
||||
2.visit(place:str,begin_time,end_time): visit somewhere from begin_time to end_time. The time should be expressed\
|
||||
as "%Y-%m-%d %H:%M", e.g. 2023-07-02 16:00. Only when Bob is at some place, he can visit it.
|
||||
3.go_to_city(origin_city:str,destination_city:str,departure_time,arrival_time,ticket_number): go to destination city from origin city, using the ticket with the ticket_number(you have known the ticket number from the database).
|
||||
4.stay_in(city:str,begin_time,end_time): stay in somewhere from begin_time to end_time. The time should be expressed\
|
||||
as "%Y-%m-%d %H:%M". Only when Bob is in some city, he can visit it.
|
||||
You should surround the plan between <plan> and </plan> such as <plan>go_to_place(\"Beijing Railway Hotel\",\"The Great Wall\",\
|
||||
\"2023-07-02 7:00\",\"2023-07-02 8:05\")</plan>, <plan>visit(\"The Great Wall\",\
|
||||
\"2023-07-02 8:05\",\"2023-07-05 17:00\")</plan>,<plan>go_to_city(\"Shanghai\",\"Beijing\",\
|
||||
\"2023-07-02 16:00\",\"2023-07-02 22:30\",\"D1111\")</plan>, <plan>stay_in(\"Beijing\",\
|
||||
\"2023-07-02 22:30\",\"2023-07-05 8:00\")</plan>
|
||||
Your ultimate goal is to give these plans, there is no need to do anything extra.
|
||||
|
||||
--- Your Workflow ---
|
||||
1. You will first be given a task.
|
||||
2. Then you will start to solve it step by step. You need to give your ideas until you need to use external tools to obtain information or calculations, and then call an action and waif for the result.
|
||||
3. Finally, call over() to indicate task completion.
|
||||
|
||||
--- Available Actions ---
|
||||
{TRAVEL_ORIGINAL_DOCUMENT}
|
||||
|
||||
<action>over()</action>
|
||||
When you think the task is completed, call "<action>over()</action>"
|
||||
|
||||
Now you will be given a task. Start planning and give me an action.
|
||||
'''
|
||||
|
||||
|
||||
TRAVEL_USER_FIRST = '''Task Requirements:
|
||||
{{task}}
|
||||
Start your planning until you need to call an action. Give me the THOUGHT and ACTION.'''
|
||||
|
||||
|
||||
TRAVEL_USER_PROMPT = """Action Result:\n{{observation}}
|
||||
Available Actions: {{action_space}}
|
||||
Continue your planning until you need an action. If the task is completed, call "<action>over()</action>".
|
||||
"""
|
||||
|
||||
|
||||
TRAVEL_EXAMPLE_MESSAGES_1 = [{'role': 'system', 'name': 'example_user',
|
||||
'content': '''Task Requirements: Bob is in Shanghai and going to travel in several cities, please make a ticket purchase plan and travel sequence for him.The demands are as follows:
|
||||
1. visit ['Beijing']. The order doesn't matter and he needs to return to Shanghai finally.
|
||||
2. He is free to travel from 2023.7.1 to 2023.7.20. The budget for transportation is 1000.0 CNY.
|
||||
3. Play at least 3 days in Beijing.
|
||||
4. If you arrive in a city before 12:00 noon, that day can be counted as a day of play. If it's past 12 o'clock, it doesn't count as a day.5. On the basis of completing the above conditions (especially the budget), spend as little time as possible.\n
|
||||
'''},
|
||||
{'role': 'system', 'name': 'example_assistant', 'content':
|
||||
'''THOUGHT:
|
||||
To fulfill Bob's travel objectives, I need to consider the following points:
|
||||
Bob needs to visit Beijing from Shanghai and then return to Shanghai.
|
||||
He has a window between 2023-07-01 to 2023-07-20 to make this trip.
|
||||
The budget for the entire journey is 1000.0 CNY.
|
||||
He wants to spend at least 3 days in Beijing.
|
||||
If he arrives in a city before 12:00 noon, the day can be counted as a play day. Otherwise, it doesn't count.
|
||||
Firstly, let's find out the available train options from Shanghai to Beijing and back. I'll query the railway database to find trains that suit Bob's schedule and budget.
|
||||
ACTION:
|
||||
I'll start by executing an SQL query to fetch 5 train options from Shanghai to Beijing, departing on or after 2023-07-01.
|
||||
<action>
|
||||
execute_sql(\'\'\'
|
||||
SELECT * FROM railway
|
||||
WHERE origin = 'Shanghai'
|
||||
AND destination = 'Beijing'
|
||||
AND DATE(departure_time) >= '2023-07-01'
|
||||
LIMIT 5;
|
||||
\'\'\')
|
||||
</action>'''},
|
||||
{'role': 'system', 'name': 'example_user',
|
||||
'content': '''Action Result:\n{\'query\': "\nSELECT * FROM railway\nWHERE origin = \'Shanghai\'\n AND destination = \'Beijing\'\n AND DATE(departure_time) >= \'2023-07-01\'\n LIMIT 5;", \'result\': [[\'D1003\', \'Shanghai\', \'Beijing\', \'2023-07-01 22:54\', \'2023-07-02 09:29\', 635, 300.0], [\'G1008\', \'Shanghai\', \'Beijing\', \'2023-07-01 06:29\', \'2023-07-01 13:19\', 410, 580.0], [\'G1013\', \'Shanghai\', \'Beijing\', \'2023-07-01 10:32\', \'2023-07-01 17:11\', 399, 580.0], [\'G1016\', \'Shanghai\', \'Beijing\', \'2023-07-01 17:05\', \'2023-07-01 20:27\', 202, 680.0], [\'D1325\', \'Shanghai\', \'Beijing\', \'2023-07-02 18:41\', \'2023-07-03 08:40\', 839, 300.0]], \'error\': None}\nAvailable Actions: [\'<action>execute_sql(statement:string)</action>\', \'<action>execute_python(code:string)</action>\', \'<action>over()</action>\']\nContinue your planning until you need an action. If the task is completed, call "<action>over()</action>".\n'''},
|
||||
{'role': 'system', 'name': 'example_assistant', 'content': '''THOUGHT:
|
||||
I've received a list of train options from Shanghai to Beijing. We can choose the cheapest ticket because we need to spend as little money as possible and have enough time. So the ticket is:
|
||||
Train D1003:
|
||||
Departure: 2023-07-01 22:54
|
||||
Arrival: 2023-07-02 09:29
|
||||
Duration: 635 minutes
|
||||
Price: 300.0 CNY
|
||||
Since Bob has a budget of 1000 CNY and wants to spend at least 3 days in Beijing, I'll keep in mind the following while selecting the train:
|
||||
1.The departure time of the train must be after 2023-07-05 09:29.
|
||||
2.The price of the ticket must be less than 1000-300=700 CNY。
|
||||
ACTION:
|
||||
Let's query the database for train options from Beijing back to Shanghai departing after 2023-07-04 (considering at least 3 days in Beijing) and the price must below 700 CNY.
|
||||
<action>execute_sql(\'\'\'
|
||||
SELECT * FROM railway
|
||||
WHERE origin = 'Beijing'
|
||||
AND destination = 'Shanghai'
|
||||
AND DATE(departure_time) >= '2023-07-05'
|
||||
AND price <= 700.0
|
||||
LIMIT 5;
|
||||
\'\'\')
|
||||
</action>
|
||||
'''},
|
||||
{'role': 'system', 'name': 'example_user',
|
||||
'content': '''OBSERVATION:\n[{'query': "\nSELECT * FROM railway\nWHERE origin = 'Shanghai'\n AND destination = 'Beijing'\n AND DATE(departure_time) >= '2023-07-01'\n LIMIT 5;", 'result': [['D1003', 'Shanghai', 'Beijing', '2023-07-01 22:54', '2023-07-02 09:29', 635, 300.0], ['G1008', 'Shanghai', 'Beijing', '2023-07-01 06:29', '2023-07-01 13:19', 410, 580.0], ['G1013', 'Shanghai', 'Beijing', '2023-07-01 10:32', '2023-07-01 17:11', 399, 580.0], ['G1016', 'Shanghai', 'Beijing', '2023-07-01 17:05', '2023-07-01 20:27', 202, 680.0], ['D1325', 'Shanghai', 'Beijing', '2023-07-02 18:41', '2023-07-03 08:40', 839, 300.0]], 'error': None}]\n'''},
|
||||
{'role': 'system', 'name': 'example_assistant', 'content': '''THOUGHT:
|
||||
I have received the train options for the journey from Beijing back to Shanghai. There are several options available that fit within Bob's budget and schedule. I should opt for the one that allows Bob to spend at least 3 days in Beijing while also being cost-effective.
|
||||
Given that Bob's departure from Shanghai to Beijing is on 2023-07-01 at 22:54 and he will arrive in Beijing on 2023-07-02 at 09:29, Bob can spend the 2nd, 3rd, and 4th of July as his play days in Beijing. So he should aim to depart from Beijing on the 5th of July or later.
|
||||
For the sake of budget and minimum stay, the best option would be to opt for the D2582 train for 300.0 CNY, which departs on 2023-07-06. This ensures he can play for 3 days in Beijing while also keeping his total expenditure to 600.0 CNY, well under the budget of 1000.0 CNY.
|
||||
Travel Plan for Bob:
|
||||
|
||||
Depart from Shanghai to Beijing on 2023-07-01 at 22:54 via train D1003. Arrive in Beijing on 2023-07-02 at 09:29.
|
||||
Duration: 635 minutes
|
||||
Price: 300.0 CNY
|
||||
Play in Beijing on 2023-07-02, 2023-07-03, and 2023-07-04.
|
||||
Depart from Beijing to Shanghai on 2023-07-06 at 09:16 via train D2582. Arrive in Shanghai on 2023-07-06 at 22:53.
|
||||
Duration: 817 minutes
|
||||
Price: 300.0 CNY
|
||||
Total expenditure: 600.0 CNY (within budget of 1000.0 CNY)
|
||||
ACTION:<action>over()</action>
|
||||
'''}
|
||||
]
|
||||
|
||||
|
||||
TRAVEL_EXAMPLE_MESSAGES_2 = [
|
||||
{'role': 'system', 'name': 'example_user',
|
||||
'content': '''Bob is going to play in Wuhan, please make a visit plan for him.The demands are as follows:
|
||||
1. He lives in Wuhan Railway Hotel. He needs to visit ['Han Show', 'Hubu Alley', 'Yellow Crane Tower', 'Tan Hua Lin', 'Baotong Temple'] and the order can be decided by you.
|
||||
2. 2 days(2023-07-06 00:00 ~ 2023-07-08 00:00) for this trip. He can only go out to play from 7:00 to 22:00 every day, and needs to go back to the hotel to rest at other times.
|
||||
3. Visit Han Show for 150 minutes, Hubu Alley for 180 minutes, Yellow Crane Tower for 240 minutes, Tan Hua Lin for 240 minutes, Baotong Temple for 300 minutes.
|
||||
4. Ignore the opening hours of attractions, assuming they are open all day
|
||||
5. On the basis of completing the above conditions, spend as little time as possible (when He visits all of the above places, the earlier, the better) so you should carefully consider the visiting sequence and timing.'''},
|
||||
|
||||
{'role': 'system', 'name': 'example_assistant', 'content':
|
||||
'''THOUGHT: To create an efficient travel plan for Bob in Wuhan, the first step is to gather information about the travel times between the hotel and each of the attractions, as well as between the attractions themselves. This will help in determining the most time-efficient sequence of visits. The attractions Bob needs to visit are Han Show, Hubu Alley, Yellow Crane Tower, Tan Hua Lin, and Baotong Temple.
|
||||
|
||||
ACTION: I will retrieve the travel duration data between these locations within Wuhan to start forming the travel sequence.
|
||||
|
||||
<action>execute_sql(\'\'\'
|
||||
SELECT origin, destination, duration FROM in_city_transport
|
||||
WHERE city = 'Wuhan' AND
|
||||
(origin IN ('Wuhan Railway Hotel', 'Han Show', 'Hubu Alley', 'Yellow Crane Tower', 'Tan Hua Lin', 'Baotong Temple') AND
|
||||
destination IN ('Wuhan Railway Hotel', 'Han Show', 'Hubu Alley', 'Yellow Crane Tower', 'Tan Hua Lin', 'Baotong Temple'));
|
||||
\'\'\')</action>'''},
|
||||
{'role': 'system', 'name': 'example_user',
|
||||
'content': '''Action Result:\n{\'query\': "\nSELECT origin, destination, duration FROM in_city_transport\nWHERE city = \'Wuhan\' AND\n(origin IN (\'Wuhan Railway Hotel\', \'Han Show\', \'Hubu Alley\', \'Yellow Crane Tower\', \'Tan Hua Lin\', \'Baotong Temple\') AND\ndestination IN (\'Wuhan Railway Hotel\', \'Han Show\', \'Hubu Alley\', \'Yellow Crane Tower\', \'Tan Hua Lin\', \'Baotong Temple\'));\n", \'result\': [[\'Han Show\', \'Yellow Crane Tower\', 67], [\'Yellow Crane Tower\', \'Han Show\', 67], [\'Baotong Temple\', \'Yellow Crane Tower\', 52], [\'Yellow Crane Tower\', \'Baotong Temple\', 52], [\'Baotong Temple\', \'Han Show\', 71], [\'Han Show\', \'Baotong Temple\', 71], [\'Tan Hua Lin\', \'Yellow Crane Tower\', 55], [\'Yellow Crane Tower\', \'Tan Hua Lin\', 55], [\'Tan Hua Lin\', \'Han Show\', 33], [\'Han Show\', \'Tan Hua Lin\', 33], [\'Tan Hua Lin\', \'Baotong Temple\', 47], [\'Baotong Temple\', \'Tan Hua Lin\', 47], [\'Hubu Alley\', \'Yellow Crane Tower\', 23], [\'Yellow Crane Tower\', \'Hubu Alley\', 23], [\'Hubu Alley\', \'Han Show\', 50], [\'Han Show\', \'Hubu Alley\', 50], [\'Hubu Alley\', \'Baotong Temple\', 75], [\'Baotong Temple\', \'Hubu Alley\', 75], [\'Hubu Alley\', \'Tan Hua Lin\', 56], [\'Tan Hua Lin\', \'Hubu Alley\', 56], [\'Wuhan Railway Hotel\', \'Yellow Crane Tower\', 72], [\'Yellow Crane Tower\', \'Wuhan Railway Hotel\', 72], [\'Wuhan Railway Hotel\', \'Han Show\', 42], [\'Han Show\', \'Wuhan Railway Hotel\', 42], [\'Wuhan Railway Hotel\', \'Baotong Temple\', 46], [\'Baotong Temple\', \'Wuhan Railway Hotel\', 46], ......], \'error\': \'\'}\nAvailable Actions: [\'<action>execute_sql(statement:string)</action>\', \'<action>execute_python(code:string)</action>\', \'<action>over()</action>\']\nContinue your planning until you need an action. If the task is completed, call "<action>over()</action>".'''},
|
||||
{'role': 'system', 'name': 'example_assistant', 'content': '''THOUGHT: With the travel durations between the attractions and the Wuhan Railway Hotel now known, the next step is to determine the most efficient sequence to visit these places. The visit durations are Han Show (150 minutes), Hubu Alley (180 minutes), Yellow Crane Tower (240 minutes), Tan Hua Lin (240 minutes), and Baotong Temple (300 minutes). Since Bob has two days for this trip and can only go out between 7:00 to 22:00, the total available time each day is 900 minutes (15 hours). I need to find an optimal route that minimizes travel time and fits within these constraints.
|
||||
ACTION: I will use the execute_python action to write and execute a script that calculates the most efficient route considering the travel and visit times. This will involve determining the best order to visit these locations to minimize total travel time while respecting the visit durations and daily time constraints.
|
||||
<action>execute_python("""# The python code is omitted in this example, but it cannot be omitted later.""")
|
||||
'''}
|
||||
]
|
||||
|
||||
|
||||
TRAVEL_EXAMPLE_MESSAGES_3 = [
|
||||
{'role': 'system', 'name': 'example_user',
|
||||
'content': '''Task Requirements: Bob is going to visit some spots across cities, please make a visit plan for him, including inter-city transportation, intra-city transportation, and visit time for each spot.The demands are as follows:\n1. He now lives in Wuhan Railway Hotel in Wuhan. In Guangzhou, he needs to visit Canton Tower for 150 minutes, Baiyun Mountain for 210 minutes.In Hangzhou, he needs to visit China National Tea Museum for 120 minutes, Quaint Water Towns for 150 minutes, Lingyin Temple for 240 minutes, West Lake for 180 minutes. And the order can be decided by you.\n2. 5 days (2023-07-9 07:00 ~ 2023-07-14 00:00) for this trip.\n3. Ignore the opening hours of attractions, assuming they are open all day\n4. On the basis of completing the above conditions (especially the time limit), spend as little money as possible.
|
||||
'''},
|
||||
|
||||
{'role': 'system', 'name': 'example_assistant', 'content':
|
||||
'''THOUGHT: Based on the requirements, Bob need to visit ["Guanzhou","Hangzhou"] and now he is in Wuhan. A simple way is to first find a random order of the cities. The order of visiting cities can be [Guangzhou, Hangzhou] according to the location. So he first needs to go to Guangzhou from Wuhan. We can first confirm his ticket to Wuhan.
|
||||
To begin planning Bob's trip, I need to find the most suitable train ticket for him to travel from Wuhan to Guangzhou. This involves checking the railway database for available train tickets, considering factors like departure times and prices to ensure his journey fits within the specified time frame and budget constraints. Once I have this information, I can decide on the best ticket option and proceed with the next steps of the trip planning.
|
||||
ACTION: To find train options from Wuhan to Guangzhou, I will query the railway database.
|
||||
<action>execute_sql(\'\'\'
|
||||
SELECT * FROM railway
|
||||
WHERE origin = 'Wuhan'
|
||||
AND destination = 'Guangzhou'
|
||||
AND DATE(departure_time) >= '2023-07-09'
|
||||
LIMIT 5;\'\'\')</action>'''},
|
||||
{'role': 'system', 'name': 'example_user',
|
||||
'content': """Action Result:\n{\'query\': "\nSELECT * FROM railway\nWHERE origin = \'Wuhan\'\nAND destination = \'Guangzhou\'\nAND DATE(departure_time) >= \'2023-07-09\'\nLIMIT 5;", \'result\': [[\'G3819\', \'Wuhan\', \'Guangzhou\', \'2023-07-09 14:49:00\', \'2023-07-09 19:28:00\', 279, 443.0], [\'G3823\', \'Wuhan\', \'Guangzhou\', \'2023-07-09 18:34:00\', \'2023-07-09 23:28:00\', 294, 443.0], [\'K3830\', \'Wuhan\', \'Guangzhou\', \'2023-07-09 13:41:00\', \'2023-07-09 23:49:00\', 608, 148.0], [\'G4131\', \'Wuhan\', \'Guangzhou\', \'2023-07-10 12:14:00\', \'2023-07-10 17:16:00\', 302, 443.0], [\'K4136\', \'Wuhan\', \'Guangzhou\', \'2023-07-10 18:51:00\', \'2023-07-11 06:45:00\', 714, 148.0]], \'error\': \'\'}\nAvailable Actions: [\'<action>execute_sql(statement:string)</action>\', \'<action>execute_python(code:string)</action>\', \'<action>over()</action>\']\nContinue your planning until you need an action. If the task is completed, call "<action>over()</action>"."""},
|
||||
{'role': 'system', 'name': 'example_assistant', 'content': '''THOUGHT: With the travel durations between the attractions and the Wuhan Railway Hotel now known, the next step is to determine the most efficient sequence to visit these places. The visit durations are Han Show (150 minutes), Hubu Alley (180 minutes), Yellow Crane Tower (240 minutes), Tan Hua Lin (240 minutes), and Baotong Temple (300 minutes). Since Bob has two days for this trip and can only go out between 7:00 to 22:00, the total available time each day is 900 minutes (15 hours). I need to find an optimal route that minimizes travel time and fits within these constraints.
|
||||
ACTION: I will use the execute_python action to write and execute a script that calculates the most efficient route considering the travel and visit times. This will involve determining the best order to visit these locations to minimize total travel time while respecting the visit durations and daily time constraints.
|
||||
<action>execute_python("""# The python code is omitted in this example, but it cannot be omitted later.""")
|
||||
'''}
|
||||
]
|
||||
|
||||
|
||||
TRAVEL_USER_OVER_PROMPT = '''Please express the part of the plan that has been confirmed in chronological order in the following formats:
|
||||
1.go_to_place(origin:str,destination:str,departure_time,arrival_time): go to destination from origin.
|
||||
2.visit(place:str,begin_time,end_time): visit somewhere from begin_time to end_time. The time should be expressed\
|
||||
as "%Y-%m-%d %H:%M", e.g. 2023-07-02 16:00.
|
||||
3.go_to_city(origin_city:str,destination_city:str,departure_time,arrival_time,ticket_number): go to destination city(such as "Beijing") from origin city, using the ticket with the ticket_number(you have known the ticket number from the database). origin_city and destination_city should be the name of city such as \"Beijing\" instead of \"Beijing Railway Hotel\".
|
||||
4.stay_in(city:str,begin_time,end_time): stay in somewhere from begin_time to end_time. The time should be expressed\
|
||||
as "%Y-%m-%d %H:%M".
|
||||
You should surround the action between <plan> and </plan> such as <plan>go_to_place(\"Beijing Railway Hotel\",\"The Great Wall\",\
|
||||
\"2023-07-02 7:00\",\"2023-07-02 8:05\")</plan>, <plan>visit(\"Great Wall\",\
|
||||
\"2023-07-02 8:05\",\"2023-07-05 17:00\")</plan>,<plan>go_to_city(\"Shanghai\",\"Beijing\",\
|
||||
\"2023-07-02 16:00\",\"2023-07-02 22:30\",\"D1111\")</plan>, <plan>stay_in(\"Beijing\",\
|
||||
\"2023-07-02 22:30\",\"2023-07-05 8:00\")</plan>'''
|
||||
@@ -20,7 +20,10 @@ class Env:
|
||||
self._name: str = self.__class__.__name__
|
||||
self.timeout: int = 2
|
||||
self.working_dir = os.path.abspath(os.path.join(__file__, "..", "..", "..", "working_dir"))
|
||||
self.env_state: EnvState | None = None
|
||||
if not os.path.exists(self.working_dir):
|
||||
os.makedirs(self.working_dir)
|
||||
|
||||
self.env_state: Union[EnvState, None] = None
|
||||
|
||||
def step(self, _command) -> EnvState:
|
||||
raise NotImplementedError
|
||||
|
||||
@@ -21,7 +21,7 @@ class PythonEnv(Env):
|
||||
super().__init__()
|
||||
self._name: str = self.__class__.__name__
|
||||
|
||||
def step(self, _command: str, args: list[str] | str = []) -> EnvState:
|
||||
def step(self, _command: str, args: Union[list[str], str] = []) -> EnvState:
|
||||
|
||||
tmp_code_file = NamedTemporaryFile("w", dir=self.working_dir, suffix=".py", encoding="utf-8")
|
||||
# wzm修改,解决拿不到最后一行输出的当前工作目录问题
|
||||
|
||||
32
openai-hk.py
Normal file
32
openai-hk.py
Normal file
@@ -0,0 +1,32 @@
|
||||
import requests
|
||||
import json
|
||||
|
||||
url = "https://api.openai-hk.com/v1/chat/completions"
|
||||
|
||||
headers = {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": "Bearer hk-y7oqw81000007081956c9eae69ef0ec39fb67374833ee3f4"
|
||||
}
|
||||
|
||||
data = {
|
||||
"max_tokens": 1200,
|
||||
"model": "gpt-4",
|
||||
"temperature": 0.8,
|
||||
"top_p": 1,
|
||||
"presence_penalty": 1,
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
"content": "You are ChatGPT, a large language model trained by OpenAI. Answer as concisely as possible."
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": "帮我写一个AppleScript代码,在macos上定一个20分钟的闹钟。"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
response = requests.post(url, headers=headers, data=json.dumps(data).encode('utf-8') )
|
||||
result = response.content.decode("utf-8")
|
||||
|
||||
print(result)
|
||||
@@ -0,0 +1,15 @@
|
||||
[
|
||||
{
|
||||
"question": "Bob is in Shanghai and going to travel in several cities, please make a ticket purchase plan and travel sequence for him.The demands are as follows:\n1. visit ['Hangzhou', 'Shanghai', 'Wuhan', 'Chengdu']. The order doesn't matter and he needs to return to Nanjing finally.\n2. 15 days (2023-07-11 00:00 ~ 2023-07-26 00:00) for this trip.\n3. Play at least 1 day in Hangzhou, 3 days in Shanghai, 3 days in Wuhan, 1 day in Chengdu.\n4. Stay in any city for a minimum of 24 hours to count as one day.\n5. On the basis of completing the above conditions (especially the time limit), spend as little money as possible.",
|
||||
"plan": "stay_in(\"Shanghai\",\"2023-07-11 00:00\",\"2023-07-14 00:00\")",
|
||||
"errors": [
|
||||
"Stay in Hangzhou for less than 1 days",
|
||||
"Stay in Shanghai for less than 3 days",
|
||||
"Stay in Wuhan for less than 3 days",
|
||||
"Stay in Chengdu for less than 1 days"
|
||||
],
|
||||
"score": 0.0,
|
||||
"over": false,
|
||||
"state": "{'error': ['Stay in Hangzhou for less than 1 days', 'Stay in Shanghai for less than 3 days', 'Stay in Wuhan for less than 3 days', 'Stay in Chengdu for less than 1 days'], 'cost': 0, 'track': [], 'e_right': 0, 'e_wrong': 0, 'i_right': 0, 'i_wrong': 4}"
|
||||
}
|
||||
]
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,34 @@
|
||||
[
|
||||
{
|
||||
"question": "Bob is in Shanghai and going to travel in several cities, please make a ticket purchase plan and travel sequence for him.The demands are as follows:\n1. visit ['Nanjing', 'Wuhan', 'Chengdu', 'Beijing']. The order doesn't matter and he needs to return to Guangzhou finally.\n2. 13 days (2023-07-06 00:00 ~ 2023-07-19 00:00) for this trip.\n3. Play at least 3 days in Nanjing, 2 days in Wuhan, 1 day in Chengdu, 1 day in Beijing.\n4. If you arrive in a city before 12:00 noon, that day can be counted as a day of play. If it's past 12 o'clock, it doesn't count as a day.5. On the basis of completing the above conditions (especially the time limit), spend as little money as possible.",
|
||||
"plan": [
|
||||
"go_to_place(\"Shanghai\",\"Nanjing\",\"2023-07-06 13:28\",\"2023-07-06 17:20\")",
|
||||
"visit(\"Nanjing\",\"2023-07-06 17:20\",\"2023-07-09 00:00\")",
|
||||
"go_to_city(\"Nanjing\",\"Wuhan\",\"2023-07-09 15:17\",\"2023-07-09 17:50\",\"G3874\")",
|
||||
"visit(\"Wuhan\",\"2023-07-09 17:50\",\"2023-07-12 00:00\")",
|
||||
"go_to_city(\"Wuhan\",\"Chengdu\",\"2023-07-12 10:05\",\"2023-07-12 16:58\",\"G4844\")",
|
||||
"visit(\"Chengdu\",\"2023-07-12 16:58\",\"2023-07-14 00:00\")",
|
||||
"go_to_city(\"Chengdu\",\"Beijing\",\"2023-07-14 10:15\",\"2023-07-14 16:30\",\"G5235\")",
|
||||
"visit(\"Beijing\",\"2023-07-14 16:30\",\"2023-07-19 00:00\")",
|
||||
"go_to_city(\"Beijing\",\"Guangzhou\",\"2023-07-19 00:00\",\"2023-07-19 00:00\",\"Ticket Number\")"
|
||||
],
|
||||
"errors": [
|
||||
"Error in \"go_to_place(Shanghai,Nanjing,2023-07-06 13:28,2023-07-06 17:20)\"\nPosition error: In None,not Shanghai",
|
||||
"Error in \"goto_city(Nanjing,Wuhan,2023-07-09 15:17,2023-07-09 17:50,G3874)\"\nTicket error: no ticket G3874",
|
||||
"Error in \"goto_city(Nanjing,Wuhan,2023-07-09 15:17,2023-07-09 17:50,G3874)\"\nPosition error: In Guangzhou,not Nanjing",
|
||||
"Error in \"visit(Wuhan,2023-07-09 17:50,2023-07-12 00:00)\"\nPosition error: In Nanjing,not Wuhan",
|
||||
"Error in \"goto_city(Wuhan,Chengdu,2023-07-12 10:05,2023-07-12 16:58,G4844)\"\nTicket error: no ticket G4844",
|
||||
"Error in \"visit(Chengdu,2023-07-12 16:58,2023-07-14 00:00)\"\nPosition error: In Wuhan,not Chengdu",
|
||||
"Error in \"goto_city(Chengdu,Beijing,2023-07-14 10:15,2023-07-14 16:30,G5235)\"\nTicket error: no ticket G5235",
|
||||
"Error in \"visit(Beijing,2023-07-14 16:30,2023-07-19 00:00)\"\nPosition error: In Chengdu,not Beijing",
|
||||
"Error in \"goto_city(Beijing,Guangzhou,2023-07-19 00:00,2023-07-19 00:00,Ticket Number)\"\nTicket error: no ticket Ticket Number",
|
||||
"Stay in Nanjing for less than 3 days",
|
||||
"Stay in Wuhan for less than 2 days",
|
||||
"Stay in Chengdu for less than 1 days",
|
||||
"Stay in Beijing for less than 1 days"
|
||||
],
|
||||
"score": 42.0,
|
||||
"over": true,
|
||||
"state": "{'error': ['Error in \"go_to_place(Shanghai,Nanjing,2023-07-06 13:28,2023-07-06 17:20)\"\\nPosition error: In None,not Shanghai', 'Error in \"goto_city(Nanjing,Wuhan,2023-07-09 15:17,2023-07-09 17:50,G3874)\"\\nTicket error: no ticket G3874', 'Error in \"goto_city(Nanjing,Wuhan,2023-07-09 15:17,2023-07-09 17:50,G3874)\"\\nPosition error: In Guangzhou,not Nanjing', 'Error in \"visit(Wuhan,2023-07-09 17:50,2023-07-12 00:00)\"\\nPosition error: In Nanjing,not Wuhan', 'Error in \"goto_city(Wuhan,Chengdu,2023-07-12 10:05,2023-07-12 16:58,G4844)\"\\nTicket error: no ticket G4844', 'Error in \"visit(Chengdu,2023-07-12 16:58,2023-07-14 00:00)\"\\nPosition error: In Wuhan,not Chengdu', 'Error in \"goto_city(Chengdu,Beijing,2023-07-14 10:15,2023-07-14 16:30,G5235)\"\\nTicket error: no ticket G5235', 'Error in \"visit(Beijing,2023-07-14 16:30,2023-07-19 00:00)\"\\nPosition error: In Chengdu,not Beijing', 'Error in \"goto_city(Beijing,Guangzhou,2023-07-19 00:00,2023-07-19 00:00,Ticket Number)\"\\nTicket error: no ticket Ticket Number', 'Stay in Nanjing for less than 3 days', 'Stay in Wuhan for less than 2 days', 'Stay in Chengdu for less than 1 days', 'Stay in Beijing for less than 1 days'], 'cost': 0, 'track': [{'begin_time': datetime.datetime(2023, 7, 6, 0, 0), 'end_time': datetime.datetime(2023, 7, 6, 13, 28), 'action': 'visit'}, {'begin_time': datetime.datetime(2023, 7, 6, 13, 28), 'end_time': datetime.datetime(2023, 7, 6, 17, 20), 'action': 'go_to_place'}, {'begin_time': datetime.datetime(2023, 7, 6, 17, 20), 'end_time': datetime.datetime(2023, 7, 9, 0, 0), 'action': 'visit'}, {'begin_time': datetime.datetime(2023, 7, 9, 0, 0), 'end_time': datetime.datetime(2023, 7, 9, 15, 17), 'action': 'stay_in'}, {'begin_time': datetime.datetime(2023, 7, 9, 17, 50), 'end_time': datetime.datetime(2023, 7, 12, 0, 0), 'action': 'visit'}, {'begin_time': datetime.datetime(2023, 7, 12, 0, 0), 'end_time': datetime.datetime(2023, 7, 12, 10, 5), 'action': 'stay_in'}, {'begin_time': datetime.datetime(2023, 7, 12, 16, 58), 'end_time': datetime.datetime(2023, 7, 14, 0, 0), 'action': 'visit'}, {'begin_time': datetime.datetime(2023, 7, 14, 0, 0), 'end_time': datetime.datetime(2023, 7, 14, 10, 15), 'action': 'stay_in'}, {'begin_time': datetime.datetime(2023, 7, 14, 16, 30), 'end_time': datetime.datetime(2023, 7, 19, 0, 0), 'action': 'visit'}], 'minutes_None': 808, 'minutes_Nanjing': 3280, 'days_Guangzhou': 0, 'minutes_Wuhan': 3250, 'days_Wuhan': 0, 'minutes_Chengdu': 1862, 'days_Chengdu': 0, 'minutes_Beijing': 6210, 'e_right': 21, 'e_wrong': 9, 'i_right': 0, 'i_wrong': 4}"
|
||||
}
|
||||
]
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,34 @@
|
||||
[
|
||||
{
|
||||
"question": "Bob is in Shanghai and going to travel in several cities, please make a ticket purchase plan and travel sequence for him.The demands are as follows:\n1. visit ['Beijing', 'Guangzhou', 'Nanjing', 'Shanghai']. The order doesn't matter and he needs to return to Wuhan finally.\n2. He is free to travel from 2023.7.1 to 2023.7.20. The budget is 1900.0 CNY.\n3. Play at least 2 days in Beijing, 3 days in Guangzhou, 2 days in Nanjing, 1 day in Shanghai.\n4. Stay in any city for a minimum of 24 hours to count as one day.\n5. On the basis of completing the above conditions (especially the budget), spend as little time as possible.",
|
||||
"plan": [
|
||||
"go_to_city(\"Shanghai\",\"Beijing\",\"2023-07-01 06:29\",\"2023-07-01 13:19\",\"G1008\")",
|
||||
"stay_in(\"Beijing\",\"2023-07-02 00:00\",\"2023-07-04 23:59\")",
|
||||
"go_to_city(\"Beijing\",\"Guangzhou\",\"2023-07-03 12:26\",\"2023-07-04 14:05\",\"K1660\")",
|
||||
"stay_in(\"Guangzhou\",\"2023-07-05 00:00\",\"2023-07-07 23:59\")",
|
||||
"go_to_city(\"Guangzhou\",\"Nanjing\",\"2023-07-06 06:41\",\"2023-07-06 15:07\",\"G2777\")",
|
||||
"stay_in(\"Nanjing\",\"2023-07-07 00:00\",\"2023-07-08 23:59\")",
|
||||
"go_to_city(\"Nanjing\",\"Shanghai\",\"2023-07-09 11:27\",\"2023-07-09 12:40\",\"G3699\")",
|
||||
"stay_in(\"Shanghai\",\"2023-07-10 00:00\",\"2023-07-10 23:59\")"
|
||||
],
|
||||
"errors": [
|
||||
"Error in \"goto_city(Shanghai,Beijing,2023-07-01 06:29,2023-07-01 13:19,G1008)\"\nTicket error: no ticket G1008",
|
||||
"Error in \"goto_city(Shanghai,Beijing,2023-07-01 06:29,2023-07-01 13:19,G1008)\"\nPosition error: In Wuhan,not Shanghai",
|
||||
"Error in \"goto_city(Shanghai,Beijing,2023-07-01 06:29,2023-07-01 13:19,G1008)\"\nTime error: already 2023-07-10 00:00:00, beyond the departure time",
|
||||
"Error in \"goto_city(Beijing,Guangzhou,2023-07-03 12:26,2023-07-04 14:05,K1660)\"\nTicket error: no ticket K1660",
|
||||
"Error in \"goto_city(Beijing,Guangzhou,2023-07-03 12:26,2023-07-04 14:05,K1660)\"\nTime error: already 2023-07-04 23:59:00, beyond the departure time",
|
||||
"Error in \"goto_city(Guangzhou,Nanjing,2023-07-06 06:41,2023-07-06 15:07,G2777)\"\nTicket error: no ticket G2777",
|
||||
"Error in \"goto_city(Guangzhou,Nanjing,2023-07-06 06:41,2023-07-06 15:07,G2777)\"\nTime error: already 2023-07-07 23:59:00, beyond the departure time",
|
||||
"Error in \"goto_city(Nanjing,Shanghai,2023-07-09 11:27,2023-07-09 12:40,G3699)\"\nTicket error: no ticket G3699",
|
||||
"Error in \"goto_city(Nanjing,Shanghai,2023-07-09 11:27,2023-07-09 12:40,G3699)\"\nCity duration error: have stayed in Nanjing for only 1 days",
|
||||
"Stay in Beijing for less than 2 days",
|
||||
"Stay in Guangzhou for less than 3 days",
|
||||
"City duration error: have stayed in Nanjing for only 1 days",
|
||||
"Stay in Nanjing for less than 2 days",
|
||||
"Stay in Shanghai for less than 1 days"
|
||||
],
|
||||
"score": 42.85714285714286,
|
||||
"over": true,
|
||||
"state": "{'error': ['Error in \"goto_city(Shanghai,Beijing,2023-07-01 06:29,2023-07-01 13:19,G1008)\"\\nTicket error: no ticket G1008', 'Error in \"goto_city(Shanghai,Beijing,2023-07-01 06:29,2023-07-01 13:19,G1008)\"\\nPosition error: In Wuhan,not Shanghai', 'Error in \"goto_city(Shanghai,Beijing,2023-07-01 06:29,2023-07-01 13:19,G1008)\"\\nTime error: already 2023-07-10 00:00:00, beyond the departure time', 'Error in \"goto_city(Beijing,Guangzhou,2023-07-03 12:26,2023-07-04 14:05,K1660)\"\\nTicket error: no ticket K1660', 'Error in \"goto_city(Beijing,Guangzhou,2023-07-03 12:26,2023-07-04 14:05,K1660)\"\\nTime error: already 2023-07-04 23:59:00, beyond the departure time', 'Error in \"goto_city(Guangzhou,Nanjing,2023-07-06 06:41,2023-07-06 15:07,G2777)\"\\nTicket error: no ticket G2777', 'Error in \"goto_city(Guangzhou,Nanjing,2023-07-06 06:41,2023-07-06 15:07,G2777)\"\\nTime error: already 2023-07-07 23:59:00, beyond the departure time', 'Error in \"goto_city(Nanjing,Shanghai,2023-07-09 11:27,2023-07-09 12:40,G3699)\"\\nTicket error: no ticket G3699', 'Error in \"goto_city(Nanjing,Shanghai,2023-07-09 11:27,2023-07-09 12:40,G3699)\"\\nCity duration error: have stayed in Nanjing for only 1 days', 'Stay in Beijing for less than 2 days', 'Stay in Guangzhou for less than 3 days', 'City duration error: have stayed in Nanjing for only 1 days', 'Stay in Nanjing for less than 2 days', 'Stay in Shanghai for less than 1 days'], 'cost': 0, 'track': [{'begin_time': datetime.datetime(2023, 7, 10, 0, 0), 'end_time': datetime.datetime(2023, 7, 1, 6, 29), 'action': 'stay_in'}, {'begin_time': datetime.datetime(2023, 7, 2, 0, 0), 'end_time': datetime.datetime(2023, 7, 4, 23, 59), 'action': 'stay_in'}, {'begin_time': datetime.datetime(2023, 7, 4, 23, 59), 'end_time': datetime.datetime(2023, 7, 3, 12, 26), 'action': 'stay_in'}, {'begin_time': datetime.datetime(2023, 7, 5, 0, 0), 'end_time': datetime.datetime(2023, 7, 7, 23, 59), 'action': 'stay_in'}, {'begin_time': datetime.datetime(2023, 7, 7, 23, 59), 'end_time': datetime.datetime(2023, 7, 6, 6, 41), 'action': 'stay_in'}, {'begin_time': datetime.datetime(2023, 7, 7, 0, 0), 'end_time': datetime.datetime(2023, 7, 8, 23, 59), 'action': 'stay_in'}, {'begin_time': datetime.datetime(2023, 7, 8, 23, 59), 'end_time': datetime.datetime(2023, 7, 9, 11, 27), 'action': 'stay_in'}, {'begin_time': datetime.datetime(2023, 7, 10, 0, 0), 'end_time': datetime.datetime(2023, 7, 10, 23, 59), 'action': 'stay_in'}], 'days_Wuhan': -9, 'days_Beijing': 0, 'days_Guangzhou': 0, 'days_Nanjing': 1, 'days_Shanghai': 0, 'e_right': 20, 'e_wrong': 8, 'i_right': 0, 'i_wrong': 4}"
|
||||
}
|
||||
]
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,15 @@
|
||||
[
|
||||
{
|
||||
"question": "Bob is in Shanghai and going to travel in several cities, please make a ticket purchase plan and travel sequence for him.The demands are as follows:\n1. visit ['Chengdu', 'Shanghai', 'Guangzhou', 'Beijing']. The order doesn't matter and he needs to return to Hangzhou finally.\n2. He is free to travel from 2023.7.1 to 2023.7.20. The budget is 4000.0 CNY.\n3. Play at least 1 day in Chengdu, 3 days in Shanghai, 3 days in Guangzhou, 2 days in Beijing.\n4. If you arrive in a city before 12:00 noon, that day can be counted as a day of play. If it's past 12 o'clock, it doesn't count as a day.5. On the basis of completing the above conditions (especially the budget), spend as little time as possible.",
|
||||
"plan": "",
|
||||
"errors": [
|
||||
"Stay in Chengdu for less than 1 days",
|
||||
"Stay in Shanghai for less than 3 days",
|
||||
"Stay in Guangzhou for less than 3 days",
|
||||
"Stay in Beijing for less than 2 days"
|
||||
],
|
||||
"score": 0.0,
|
||||
"over": false,
|
||||
"state": "{'error': ['Stay in Chengdu for less than 1 days', 'Stay in Shanghai for less than 3 days', 'Stay in Guangzhou for less than 3 days', 'Stay in Beijing for less than 2 days'], 'cost': 0, 'track': [], 'e_right': 0, 'e_wrong': 0, 'i_right': 0, 'i_wrong': 4}"
|
||||
}
|
||||
]
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
28
tasks/travel/run_task/general.py
Normal file
28
tasks/travel/run_task/general.py
Normal file
@@ -0,0 +1,28 @@
|
||||
import os
|
||||
|
||||
class ConfigManager:
|
||||
_instance = None
|
||||
|
||||
def __new__(cls):
|
||||
if cls._instance is None:
|
||||
cls._instance = super(ConfigManager, cls).__new__(cls)
|
||||
cls._instance.http_proxy = "http://127.0.0.1:10809"
|
||||
cls._instance.https_proxy = "http://127.0.0.1:10809"
|
||||
# cls._instance.http_proxy = None
|
||||
# cls._instance.https_proxy = None
|
||||
return cls._instance
|
||||
|
||||
def set_proxies(self, http, https):
|
||||
self.http_proxy = http
|
||||
self.https_proxy = https
|
||||
|
||||
def apply_proxies(self):
|
||||
if self.http_proxy:
|
||||
os.environ["http_proxy"] = self.http_proxy
|
||||
if self.https_proxy:
|
||||
os.environ["https_proxy"] = self.https_proxy
|
||||
|
||||
def clear_proxies(self):
|
||||
os.environ.pop("http_proxy", None)
|
||||
os.environ.pop("https_proxy", None)
|
||||
|
||||
232
tasks/travel/run_task/run.py
Normal file
232
tasks/travel/run_task/run.py
Normal file
@@ -0,0 +1,232 @@
|
||||
import copy
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import time
|
||||
|
||||
import openai
|
||||
import requests
|
||||
|
||||
from jarvis.agent.react_agent import ReactAgent
|
||||
from jarvis.agent.openai_agent import OpenAIAgent
|
||||
from simulator import TravelSimulator
|
||||
# from utils.code import get_content, get_content_list
|
||||
# from utils.config_manager import ConfigManager
|
||||
# from utils.travel import execute_sql,execute_python
|
||||
from general import ConfigManager
|
||||
|
||||
|
||||
TASK = '''Bob is in Beijing and going to travel in several cities, please make a ticket purchase plan and travel sequence for him.The demands are as follows:
|
||||
1. visit ['Chengdu']. The order doesn't matter and he needs to return to Beijing finally.
|
||||
2. He is free to travel from 2023.7.1 to 2023.7.20. The budget for transportation is 1800.0 CNY.
|
||||
3. Play at least 1 day in Chengdu.
|
||||
4. Stay in any city for a minimum of 24 hours to count as one day.
|
||||
5. On the basis of completing the above conditions (especially the budget), spend as little time as possible.
|
||||
'''
|
||||
|
||||
# os.environ['OPENAI_API_KEY'] = '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'
|
||||
os.environ['OPENAI_API_KEY'] = 'hk-y7oqw81000007081956c9eae69ef0ec39fb67374833ee3f4'
|
||||
# model_name = 'gpt-3.5-turbo-16k-0613'
|
||||
model_name = 'gpt-4-1106-preview'
|
||||
MAX_ITER = 3
|
||||
level = 1
|
||||
begin = 24
|
||||
end = 99
|
||||
step = 1
|
||||
|
||||
|
||||
|
||||
def get_content(s, begin_str='[BEGIN]', end_str='[END]'):
|
||||
_begin = s.find(begin_str)
|
||||
_end = s.find(end_str)
|
||||
if _begin == -1 or _end == -1:
|
||||
return ''
|
||||
else:
|
||||
return s[_begin + len(begin_str):_end].strip()
|
||||
|
||||
|
||||
def get_content_list(s, begin_str='[BEGIN]', end_str='[END]'):
|
||||
result = []
|
||||
_begin = s.find(begin_str)
|
||||
if _begin>=0:
|
||||
_end = s[_begin + len(begin_str):].find(end_str) + _begin + len(begin_str)
|
||||
else:
|
||||
_end = s.find(end_str)
|
||||
while not (_begin == -1 or _end == -1):
|
||||
result.append(s[_begin + len(begin_str):_end].strip())
|
||||
s = s[_end + len(end_str):]
|
||||
_begin = s.find(begin_str)
|
||||
_end = s.find(end_str)
|
||||
unique_result = []
|
||||
for item in result:
|
||||
if item not in unique_result:
|
||||
unique_result.append(item)
|
||||
return unique_result
|
||||
|
||||
|
||||
def query_database(query: list):
|
||||
# config_manager.clear_proxies()
|
||||
try:
|
||||
response = requests.post(
|
||||
"http://localhost:8079/tools/database",
|
||||
json={'queries': query}
|
||||
)
|
||||
response = response.json()
|
||||
if len(response) > 0:
|
||||
response = response[0]
|
||||
except Exception as e:
|
||||
response = {'result': f'error', 'error': f'run error{e}'}
|
||||
print(response)
|
||||
# config_manager.apply_proxies()
|
||||
return re.sub(r'\\n', '\n', str(response))
|
||||
# return str(response)
|
||||
|
||||
|
||||
def execute_sql(statement: str):
|
||||
return query_database([statement])
|
||||
|
||||
|
||||
def execute_python(code: str):
|
||||
config_manager.clear_proxies()
|
||||
response = requests.post(
|
||||
'http://127.0.0.1:8079/tools/python',
|
||||
json={'code': code}
|
||||
)
|
||||
config_manager.apply_proxies()
|
||||
result=response.json()
|
||||
return str(result)
|
||||
|
||||
|
||||
def invoke_function(func_data):
|
||||
func = globals()[func_data['function_name']]
|
||||
result = func(*func_data['args'])
|
||||
return result
|
||||
|
||||
|
||||
def run_item(task, agent, output_path="."):
|
||||
plan_strs = []
|
||||
max_iter = MAX_ITER
|
||||
if level == 1:
|
||||
from jarvis.core.prompt import TRAVEL_EXAMPLE_MESSAGES_1
|
||||
main_agent = ReactAgent(model_name=model_name, task=task,
|
||||
record_path=f'{output_path}/react_agent_record.json',
|
||||
example_message=TRAVEL_EXAMPLE_MESSAGES_1)
|
||||
elif level == 2:
|
||||
from jarvis.core.prompt import TRAVEL_EXAMPLE_MESSAGES_2
|
||||
main_agent = ReactAgent(model_name=model_name, task=task,
|
||||
record_path=f'{output_path}/react_agent_record.json',
|
||||
example_message=TRAVEL_EXAMPLE_MESSAGES_2)
|
||||
elif level == 3:
|
||||
from jarvis.core.prompt import TRAVEL_EXAMPLE_MESSAGES_3
|
||||
main_agent = ReactAgent(model_name=model_name, task=task,
|
||||
record_path=f'{output_path}/react_agent_record.json',
|
||||
example_message=TRAVEL_EXAMPLE_MESSAGES_3)
|
||||
|
||||
cur_iter = 0
|
||||
completed = False
|
||||
try:
|
||||
if 'gpt-4' in model_name:
|
||||
session = requests.Session()
|
||||
else:
|
||||
session = None
|
||||
while cur_iter < max_iter:
|
||||
call_over = False
|
||||
cur_iter += 1
|
||||
response = main_agent.get_response(session)
|
||||
text = response['content']
|
||||
functions = main_agent.parse_functions(text)
|
||||
observation = f'No valid action found.\nAvailable actions:{main_agent.get_action_space()}\nGive me the action between <action> and </action>.'
|
||||
for function in functions:
|
||||
try:
|
||||
if function['function_name'] == 'over':
|
||||
call_over = True
|
||||
observation = invoke_function(function)
|
||||
break
|
||||
except Exception as e:
|
||||
observation = f'{e}. No valid action found. Available actions:{main_agent.get_action_space()}\n Give me the action between <action> and </action>. Make sure to pass in the correct parameters'
|
||||
print(e)
|
||||
|
||||
if call_over:
|
||||
completed = True
|
||||
main_agent.add_over_prompt()
|
||||
response = main_agent.get_response(session)
|
||||
text = response['content']
|
||||
plan_strs = get_content_list(text, begin_str='<plan>', end_str='</plan>')
|
||||
break
|
||||
print(f'observation={observation}')
|
||||
main_agent.add_user_prompt(observation)
|
||||
if cur_iter >= max_iter:
|
||||
main_agent.add_over_prompt()
|
||||
response = main_agent.get_response(session)
|
||||
text = response['content']
|
||||
plan_strs = get_content(text, begin_str='<plan>', end_str='</plan>')
|
||||
# except openai.error.InvalidRequestError as e:
|
||||
except openai.BadRequestError as e:
|
||||
print(f'{e} InvalidRequestError. Context length error?')
|
||||
for idx in range(len(main_agent.messages) - 1, 0, -1):
|
||||
if main_agent.messages[idx]["role"] == "user":
|
||||
break
|
||||
main_agent.messages = main_agent.messages[:idx - 2] # 从后往前删掉idx:user, idx-1:assistant, idx-2:user
|
||||
main_agent.add_over_prompt()
|
||||
response = main_agent.get_response(session)
|
||||
text = response['content']
|
||||
plan_strs = get_content_list(text, begin_str='<plan>', end_str='</plan>')
|
||||
finally:
|
||||
if session is not None:
|
||||
session.close()
|
||||
# except Exception as e:
|
||||
# print(f'{e} InvalidRequestError. Context length error?')
|
||||
# for idx in range(len(main_agent.messages) - 1, 0, -1):
|
||||
# if main_agent.messages[idx]["role"] == "user":
|
||||
# break
|
||||
# main_agent.messages = main_agent.messages[:idx - 2] # 从后往前删掉idx:user, idx-1:assistant, idx-2:user
|
||||
# main_agent.add_over_prompt()
|
||||
# response = main_agent.get_response()
|
||||
# text = response['content']
|
||||
# plan_strs = get_content_list(text, begin_str='<plan>', end_str='</plan>')
|
||||
|
||||
return plan_strs, completed
|
||||
|
||||
|
||||
def run(level, agent):
|
||||
output_dir = f'./output/travel/react_style/{agent.llm.model_name}/level{level}'
|
||||
data_path = f'./tasks/travel/data/data_level1.json'
|
||||
with open(data_path, 'r', encoding='utf-8') as file:
|
||||
data = json.load(file)
|
||||
data = data[begin:end:step]
|
||||
for data_idx, d in enumerate(data):
|
||||
print(f'data_idx={data_idx}')
|
||||
prediction = []
|
||||
# try:
|
||||
print(f'{data_idx}:{time.localtime()}')
|
||||
task_id = begin + data_idx * step
|
||||
output_path = f'{output_dir}/{task_id}'
|
||||
if not os.path.exists(output_path):
|
||||
os.makedirs(output_path)
|
||||
prediction_file = f'{output_path}/prediction.json'
|
||||
task = d['question']
|
||||
simulator = TravelSimulator(**d['demands']['TravelSimulator'])
|
||||
simulator.create_constraints(d['demands']['Constraints'])
|
||||
plan_strs, completed = run_item(task=task, agent=agent, output_path=output_path)
|
||||
for plan_str in plan_strs:
|
||||
print(f'plan_str={plan_str}')
|
||||
simulator.action(plan_str)
|
||||
simulator.over()
|
||||
print(f'geterror')
|
||||
errors = simulator.get_errors()
|
||||
score = simulator.get_score()
|
||||
print(f'state={simulator.state}')
|
||||
prediction.append(
|
||||
{"question": d['question'], "plan": plan_strs, "errors": errors, "score": score,
|
||||
"over": completed, "state": str(simulator.state)})
|
||||
print(f'prediction={prediction}')
|
||||
with open(prediction_file, 'w', encoding='utf-8') as f:
|
||||
json.dump(prediction, f, indent=4, ensure_ascii=False)
|
||||
# except Exception as e:
|
||||
# print(f'{data_idx}:{e}')
|
||||
|
||||
|
||||
config_manager = ConfigManager()
|
||||
agent = OpenAIAgent(config_path="examples/config.json")
|
||||
for level in [1,2,3]:
|
||||
run(level, agent)
|
||||
72
tasks/travel/run_task/serve.py
Normal file
72
tasks/travel/run_task/serve.py
Normal file
@@ -0,0 +1,72 @@
|
||||
import os
|
||||
|
||||
from fastapi import FastAPI
|
||||
from general import ConfigManager
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
# Import your services
|
||||
from api.python.interpreter import router as python_router
|
||||
from api.arxiv.arxiv import router as arxiv_router
|
||||
from api.bing.bing_service import router as bing_router
|
||||
from api.calculator.calculator import router as calculator_router
|
||||
from api.chemical.chemical import router as chemical_router
|
||||
from api.ppt.ppt import router as ppt_router
|
||||
from api.shell.shell import router as shell_router
|
||||
from api.database.database import router as db_router
|
||||
from api.wolfram_alpha.wolfram_alpha import router as wa_router
|
||||
from api.weather.weather import router as weather_router # 新增这一行
|
||||
from api.google_calendar.calendar_service import router as calendar_router
|
||||
from api.gmail.gmail import router as gmail_router # 新增这一行
|
||||
|
||||
from starlette.middleware.base import BaseHTTPMiddleware
|
||||
from starlette.requests import Request
|
||||
|
||||
|
||||
class LoggingMiddleware(BaseHTTPMiddleware):
|
||||
async def dispatch(self, request: Request, call_next):
|
||||
print(f"Incoming request: {request.method} {request.url}")
|
||||
try:
|
||||
response = await call_next(request)
|
||||
except Exception as e:
|
||||
print(f"Request error: {str(e)}")
|
||||
raise e from None
|
||||
else:
|
||||
print(f"Outgoing response: {response.status_code}")
|
||||
return response
|
||||
|
||||
|
||||
app.add_middleware(LoggingMiddleware)
|
||||
|
||||
# Create a dictionary that maps service names to their routers
|
||||
services = {
|
||||
"python_executor": python_router,
|
||||
"calculator": calculator_router,
|
||||
"arxiv": arxiv_router,
|
||||
"bing": bing_router,
|
||||
"chemical": chemical_router,
|
||||
"ppt": ppt_router,
|
||||
"shell": shell_router,
|
||||
"database": db_router,
|
||||
"wolframalpha": wa_router,
|
||||
"weather": weather_router,
|
||||
"calendar": calendar_router,
|
||||
"gmail": gmail_router
|
||||
|
||||
}
|
||||
|
||||
server_list = ["python_executor", "calculator","arxiv","bing","shell","ppt",
|
||||
"database","wolframalpha","weather","calendar","gmail"]
|
||||
|
||||
# Include only the routers for the services listed in server_list
|
||||
for service in server_list:
|
||||
if service in services:
|
||||
app.include_router(services[service])
|
||||
|
||||
proxy_manager = ConfigManager()
|
||||
proxy_manager.apply_proxies()
|
||||
|
||||
if __name__ == "__main__":
|
||||
import uvicorn
|
||||
|
||||
uvicorn.run(app, host="127.0.0.1", port=8079)
|
||||
@@ -44,24 +44,18 @@ def get_ticket(number):
|
||||
return ticket
|
||||
|
||||
|
||||
print(get_ticket('D1000'))
|
||||
# def get_opening_hours(spot):
|
||||
# query = f"SELECT * FROM place\nWHERE name = '{spot}';"
|
||||
# config_manager.clear_proxies()
|
||||
|
||||
|
||||
def get_opening_hours(spot):
|
||||
query = f"SELECT * FROM place\nWHERE name = '{spot}';"
|
||||
config_manager.clear_proxies()
|
||||
|
||||
item = query_database(query)
|
||||
config_manager.apply_proxies()
|
||||
if item is None or len(item) == 0:
|
||||
return None
|
||||
item = item[0]
|
||||
opening_hours_begin = item[3]
|
||||
opening_hours_end = item[4]
|
||||
return opening_hours_begin, opening_hours_end
|
||||
|
||||
|
||||
print(get_opening_hours('Tiananmen Square'))
|
||||
# item = query_database(query)
|
||||
# config_manager.apply_proxies()
|
||||
# if item is None or len(item) == 0:
|
||||
# return None
|
||||
# item = item[0]
|
||||
# opening_hours_begin = item[3]
|
||||
# opening_hours_end = item[4]
|
||||
# return opening_hours_begin, opening_hours_end
|
||||
|
||||
|
||||
def get_in_city_transport(origin, destination):
|
||||
@@ -390,3 +384,7 @@ class TravelSimulator:
|
||||
if score == 80:
|
||||
score += advanced_score
|
||||
return score
|
||||
|
||||
|
||||
# print(get_opening_hours('Tiananmen Square'))
|
||||
# print(get_ticket('D1000'))
|
||||
Reference in New Issue
Block a user