Spaces:
Sleeping
Sleeping
omkarenator
commited on
Commit
•
b8cdbfb
0
Parent(s):
Initial commit
Browse files- .gitattributes +34 -0
- .github/README.md +1 -0
- .github/workflows/sync-to-hf.yaml +20 -0
- .gitignore +28 -0
- LICENSE +21 -0
- README-main.md +103 -0
- README.md +13 -0
- autoagents/__init__.py +0 -0
- autoagents/agents/__init__.py +0 -0
- autoagents/agents/search.py +267 -0
- autoagents/spaces/app.py +145 -0
- autoagents/tools/__init__.py +0 -0
- autoagents/tools/tools.py +70 -0
- autoagents/utils/__init__.py +0 -0
- autoagents/utils/constants.py +21 -0
- autoagents/utils/logger.py +60 -0
- autoagents/utils/utils.py +8 -0
- requirements.txt +5 -0
- setup.py +7 -0
- test.py +52 -0
.gitattributes
ADDED
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
*.7z filter=lfs diff=lfs merge=lfs -text
|
2 |
+
*.arrow filter=lfs diff=lfs merge=lfs -text
|
3 |
+
*.bin filter=lfs diff=lfs merge=lfs -text
|
4 |
+
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
5 |
+
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
6 |
+
*.ftz filter=lfs diff=lfs merge=lfs -text
|
7 |
+
*.gz filter=lfs diff=lfs merge=lfs -text
|
8 |
+
*.h5 filter=lfs diff=lfs merge=lfs -text
|
9 |
+
*.joblib filter=lfs diff=lfs merge=lfs -text
|
10 |
+
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
11 |
+
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
12 |
+
*.model filter=lfs diff=lfs merge=lfs -text
|
13 |
+
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
14 |
+
*.npy filter=lfs diff=lfs merge=lfs -text
|
15 |
+
*.npz filter=lfs diff=lfs merge=lfs -text
|
16 |
+
*.onnx filter=lfs diff=lfs merge=lfs -text
|
17 |
+
*.ot filter=lfs diff=lfs merge=lfs -text
|
18 |
+
*.parquet filter=lfs diff=lfs merge=lfs -text
|
19 |
+
*.pb filter=lfs diff=lfs merge=lfs -text
|
20 |
+
*.pickle filter=lfs diff=lfs merge=lfs -text
|
21 |
+
*.pkl filter=lfs diff=lfs merge=lfs -text
|
22 |
+
*.pt filter=lfs diff=lfs merge=lfs -text
|
23 |
+
*.pth filter=lfs diff=lfs merge=lfs -text
|
24 |
+
*.rar filter=lfs diff=lfs merge=lfs -text
|
25 |
+
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
26 |
+
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
27 |
+
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
28 |
+
*.tflite filter=lfs diff=lfs merge=lfs -text
|
29 |
+
*.tgz filter=lfs diff=lfs merge=lfs -text
|
30 |
+
*.wasm filter=lfs diff=lfs merge=lfs -text
|
31 |
+
*.xz filter=lfs diff=lfs merge=lfs -text
|
32 |
+
*.zip filter=lfs diff=lfs merge=lfs -text
|
33 |
+
*.zst filter=lfs diff=lfs merge=lfs -text
|
34 |
+
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
.github/README.md
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
../README-main.md
|
.github/workflows/sync-to-hf.yaml
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
name: Sync to Hugging Face hub
|
2 |
+
on:
|
3 |
+
push:
|
4 |
+
branches: [main]
|
5 |
+
|
6 |
+
# to run this workflow manually from the Actions tab
|
7 |
+
workflow_dispatch:
|
8 |
+
|
9 |
+
jobs:
|
10 |
+
sync-to-hub:
|
11 |
+
runs-on: ubuntu-latest
|
12 |
+
steps:
|
13 |
+
- uses: actions/checkout@v3
|
14 |
+
with:
|
15 |
+
fetch-depth: 0
|
16 |
+
lfs: true
|
17 |
+
- name: Push to hub
|
18 |
+
env:
|
19 |
+
HF_TOKEN: ${{ secrets.HF_TOKEN }}
|
20 |
+
run: git push https://omkarenator:$HF_TOKEN@huggingface.co/spaces/AutoLLM/AutoAgents main
|
.gitignore
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Byte-compiled / optimized / DLL files
|
2 |
+
__pycache__/
|
3 |
+
*.py[cod]
|
4 |
+
*$py.class
|
5 |
+
|
6 |
+
# C extensions
|
7 |
+
*.so
|
8 |
+
|
9 |
+
# Distribution / packaging
|
10 |
+
.Python
|
11 |
+
build/
|
12 |
+
develop-eggs/
|
13 |
+
dist/
|
14 |
+
downloads/
|
15 |
+
eggs/
|
16 |
+
.eggs/
|
17 |
+
lib/
|
18 |
+
lib64/
|
19 |
+
parts/
|
20 |
+
sdist/
|
21 |
+
var/
|
22 |
+
wheels/
|
23 |
+
share/python-wheels/
|
24 |
+
*.egg-info/
|
25 |
+
.installed.cfg
|
26 |
+
*.egg
|
27 |
+
MANIFEST
|
28 |
+
.DS_Store
|
LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
MIT License
|
2 |
+
|
3 |
+
Copyright (c) 2023 AutoLLM
|
4 |
+
|
5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6 |
+
of this software and associated documentation files (the "Software"), to deal
|
7 |
+
in the Software without restriction, including without limitation the rights
|
8 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9 |
+
copies of the Software, and to permit persons to whom the Software is
|
10 |
+
furnished to do so, subject to the following conditions:
|
11 |
+
|
12 |
+
The above copyright notice and this permission notice shall be included in all
|
13 |
+
copies or substantial portions of the Software.
|
14 |
+
|
15 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21 |
+
SOFTWARE.
|
README-main.md
ADDED
@@ -0,0 +1,103 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# AutoAgents
|
2 |
+
|
3 |
+
<p align="center"><img src="https://raw.githubusercontent.com/AutoLLM/AutoAgents/assets/images/logo.png?raw=true" width=400/></p>
|
4 |
+
|
5 |
+
Unlock complex question answering in LLMs with enhanced chain-of-thought reasoning and information-seeking capabilities.
|
6 |
+
|
7 |
+
## 👉 Overview
|
8 |
+
|
9 |
+
The purpose of this project is to extend LLMs ability to answer more complex questions through chain-of-thought reasoning and information-seeking actions.
|
10 |
+
|
11 |
+
We are excited to release the initial version of AutoAgents, a proof-of-concept on what can be achieved with only well-written prompts. This is the initial step towards our first big milestone, releasing and open-sourcing the AutoAgents 7B model!
|
12 |
+
|
13 |
+
Come try out our [Huggingface Space](https://huggingface.co/spaces/AutoLLM/AutoAgents)!
|
14 |
+
|
15 |
+
|
16 |
+
|
17 |
+
## 🤖 The AutoAgents Project
|
18 |
+
|
19 |
+
This project demonstrates LLMs capability to execute a complex user goal: understand a user's goal, generate a plan, use proper tools, and deliver a final result.
|
20 |
+
|
21 |
+
For simplicity, our first attempt starts with a Web Search Agent.
|
22 |
+
|
23 |
+
|
24 |
+
|
25 |
+
## 💫 How it works:
|
26 |
+
|
27 |
+
<p align="left"><img src="https://raw.githubusercontent.com/AutoLLM/AutoAgents/assets/images/agent.png" width=830/></p>
|
28 |
+
|
29 |
+
|
30 |
+
|
31 |
+
## 📔 Examples
|
32 |
+
|
33 |
+
Ask your AutoAgent to do what a real person would do using the internet:
|
34 |
+
|
35 |
+
For example:
|
36 |
+
|
37 |
+
*1. Recommend a kid friendly movie that is playing at a theater near Sunnyvale. Give me the showtimes and a link to purchase the tickets*
|
38 |
+
|
39 |
+
*2. What is the average age of the past three president when they took office*
|
40 |
+
|
41 |
+
*3. What is the mortgage rate right now and how does that compare to the past two years*
|
42 |
+
|
43 |
+
|
44 |
+
|
45 |
+
## 💁 Roadmap
|
46 |
+
|
47 |
+
* ~~HuggingFace Space demo using OpenAI models~~ [LINK](https://huggingface.co/spaces/AutoLLM/AutoAgents)
|
48 |
+
* AutoAgents [7B] Model
|
49 |
+
* Initial Release:
|
50 |
+
* Finetune and release a 7B parameter fine-tuned search model
|
51 |
+
* AutoAgents Dataset
|
52 |
+
* A high-quality dataset for a diverse set of search scenarios (why quality and diversity?<sup>[1](https://arxiv.org/abs/2305.11206)</sup>)
|
53 |
+
* Reduce Model Inference Overhead
|
54 |
+
* Affordance Modeling <sup>[2](https://en.wikipedia.org/wiki/Affordance)</sup>
|
55 |
+
* Extend Support to Additional Tools
|
56 |
+
* Customizable Document Search set (e.g. personal documents)
|
57 |
+
* Support Multi-turn Dialogue
|
58 |
+
* Advanced Flow Control in Plan Execution
|
59 |
+
|
60 |
+
We are actively developing a few interesting things, check back here or follow us on [Twitter](https://twitter.com/AutoLLM) for any new development.
|
61 |
+
|
62 |
+
If you are interested in any other problems, feel free to shoot us an issue.
|
63 |
+
|
64 |
+
|
65 |
+
|
66 |
+
## 🧭 How to use this repo?
|
67 |
+
|
68 |
+
This repo contains the entire code to run the search agent from your local browser. All you need is an OpenAI API key to begin.
|
69 |
+
|
70 |
+
To run the search agent locally:
|
71 |
+
|
72 |
+
1. Clone the repo and change the directory
|
73 |
+
|
74 |
+
```bash
|
75 |
+
git clone https://github.com/AutoLLM/AutoAgents.git
|
76 |
+
cd AutoAgents
|
77 |
+
```
|
78 |
+
|
79 |
+
2. Install the dependencies
|
80 |
+
|
81 |
+
```bash
|
82 |
+
pip install -r requirements.txt
|
83 |
+
```
|
84 |
+
|
85 |
+
3. Install the `autoagents` package
|
86 |
+
|
87 |
+
```bash
|
88 |
+
pip install -e .
|
89 |
+
```
|
90 |
+
|
91 |
+
4. Make sure you have your OpenAI API key set as an environment variable. Alternatively, you can also feed it through the input text-box on the sidebar.
|
92 |
+
|
93 |
+
```bash
|
94 |
+
export OPENAI_API_KEY=sk-xxxxxx
|
95 |
+
```
|
96 |
+
|
97 |
+
5. Run the Streamlit app
|
98 |
+
|
99 |
+
```bash
|
100 |
+
streamlit run autoagents/spaces/app.py
|
101 |
+
```
|
102 |
+
|
103 |
+
This should open a browser window where you can type your search query.
|
README.md
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
---
|
2 |
+
title: AutoAgents
|
3 |
+
emoji: 🐢
|
4 |
+
colorFrom: green
|
5 |
+
colorTo: purple
|
6 |
+
sdk: streamlit
|
7 |
+
sdk_version: 1.21.0
|
8 |
+
python_version: 3.10.11
|
9 |
+
app_file: autoagents/spaces/app.py
|
10 |
+
pinned: true
|
11 |
+
---
|
12 |
+
|
13 |
+
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
autoagents/__init__.py
ADDED
File without changes
|
autoagents/agents/__init__.py
ADDED
File without changes
|
autoagents/agents/search.py
ADDED
@@ -0,0 +1,267 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from typing import List, Union, Any, Optional, Dict
|
2 |
+
import uuid
|
3 |
+
import re
|
4 |
+
from datetime import date
|
5 |
+
import asyncio
|
6 |
+
from collections import defaultdict
|
7 |
+
import os
|
8 |
+
|
9 |
+
from langchain.agents import Tool, AgentExecutor, LLMSingleActionAgent, AgentOutputParser
|
10 |
+
from langchain.prompts import StringPromptTemplate
|
11 |
+
from langchain import LLMChain
|
12 |
+
from langchain.chat_models import ChatOpenAI
|
13 |
+
from langchain.schema import AgentAction, AgentFinish
|
14 |
+
from langchain.callbacks import get_openai_callback
|
15 |
+
from langchain.callbacks.base import AsyncCallbackHandler
|
16 |
+
from langchain.callbacks.manager import AsyncCallbackManager
|
17 |
+
|
18 |
+
|
19 |
+
from autoagents.tools.tools import search_tool, note_tool, rewrite_search_query
|
20 |
+
from autoagents.utils.logger import InteractionsLogger
|
21 |
+
from autoagents.utils.utils import OpenAICred
|
22 |
+
|
23 |
+
|
24 |
+
# Set up the base template
|
25 |
+
template = """
|
26 |
+
We are working together to satisfy the user's original goal step-by-step. Play to your strengths as an LLM.
|
27 |
+
Make sure the plan is achievable using the
|
28 |
+
available tools. You SHOULD directly produce a `Final Answer:` when you
|
29 |
+
think you have good-enough information to achieve the Goal. The final answer should be descriptive should be descriptive, encompassing all relevant details..
|
30 |
+
Today is {today}.
|
31 |
+
|
32 |
+
## Goal:
|
33 |
+
{input}
|
34 |
+
|
35 |
+
If you require assistance or additional information, you should use *only* one of the following tools:
|
36 |
+
{tools}.
|
37 |
+
|
38 |
+
## Output format
|
39 |
+
You MUST produce Output in the following format:
|
40 |
+
|
41 |
+
Thought: you should always think about what to do when you think you have not achieved the Goal.
|
42 |
+
Reasoning: reasoning
|
43 |
+
Plan:
|
44 |
+
- short bulleted
|
45 |
+
- list that conveys
|
46 |
+
- next-step plan
|
47 |
+
Action: the action to take, should be ONE OF {tool_names}
|
48 |
+
Action Input: the input to the Action
|
49 |
+
Observation: the result of the Action
|
50 |
+
... (this Thought/Reasoning/Plan/Action/Action Input/Observation can repeat N
|
51 |
+
times until there is a Final Answer)
|
52 |
+
Final Answer: the final answer to achieve the original Goal which can be the
|
53 |
+
only output or when you have no Action to do next.
|
54 |
+
|
55 |
+
## History
|
56 |
+
{agent_scratchpad}
|
57 |
+
|
58 |
+
Do not repeat any past actions in History, because you will not get additional information.
|
59 |
+
If the last action is search, then you should use notepad to keep critical information.
|
60 |
+
If you have gathered all information in your plannings to satisfy the user's original goal, then respond immediately as the Final Answer.
|
61 |
+
"""
|
62 |
+
|
63 |
+
|
64 |
+
# Set up a prompt template
|
65 |
+
class CustomPromptTemplate(StringPromptTemplate):
|
66 |
+
# The template to use
|
67 |
+
template: str
|
68 |
+
# The list of tools available
|
69 |
+
tools: List[Tool]
|
70 |
+
ialogger: InteractionsLogger
|
71 |
+
|
72 |
+
def format(self, **kwargs) -> str:
|
73 |
+
# Get the intermediate steps (AgentAction, Observation tuples)
|
74 |
+
# Format them in a particular way
|
75 |
+
intermediate_steps = kwargs.pop("intermediate_steps")
|
76 |
+
outputs = ""
|
77 |
+
# Set the agent_scratchpad variable to that value
|
78 |
+
for action, observation in intermediate_steps[:-1]:
|
79 |
+
outputs += f"{action.log}\n"
|
80 |
+
if len(intermediate_steps) > 0:
|
81 |
+
action, observation = intermediate_steps[-1]
|
82 |
+
# self.ialogger.add_system({"action": action, "observation": observation})
|
83 |
+
if action.tool not in ("Search", "Notepad"):
|
84 |
+
raise Exception("Invalid tool requested by the model.")
|
85 |
+
if action.tool == "Notepad":
|
86 |
+
outputs += f"{action.log}\n"
|
87 |
+
outputs += f"Observation: {observation}\n"
|
88 |
+
elif action.tool == "Search":
|
89 |
+
current = "".join([f"{d}" for d in observation])
|
90 |
+
outputs += f"{action.log}\n"
|
91 |
+
outputs += f"Observation: {current}\n"
|
92 |
+
|
93 |
+
# Parse the output ofr the last step for the reasoning and plan
|
94 |
+
regex = r"Thought\s*\d*\s*:(.*?)\n(.*)"
|
95 |
+
match = re.search(regex, action.log, re.DOTALL)
|
96 |
+
thoughts = match.group(1).strip() if match else ""
|
97 |
+
|
98 |
+
regex = r"Reasoning\s*\d*\s*:(.*?)\n(.*)"
|
99 |
+
match = re.search(regex, action.log, re.DOTALL)
|
100 |
+
reasoning = match.group(1).strip() if match else ""
|
101 |
+
|
102 |
+
regex = r"Plan\s*\d*\s*:(.*?)\nAction(.*)"
|
103 |
+
match = re.search(regex, action.log, re.DOTALL)
|
104 |
+
plans = match.group(1).strip() if match else ""
|
105 |
+
self.ialogger.add_structured_data({"output":{"thoughts": thoughts,
|
106 |
+
"reasoning": reasoning,
|
107 |
+
"plans": plans,
|
108 |
+
"action": action.tool,
|
109 |
+
"action_input": action.tool_input,
|
110 |
+
"raw_output":action.log},
|
111 |
+
"observation": observation})
|
112 |
+
kwargs["agent_scratchpad"] = outputs
|
113 |
+
# Create a tools variable from the list of tools provided
|
114 |
+
kwargs["tools"] = "\n".join([f"{tool.name}: {tool.description}" for tool in self.tools])
|
115 |
+
# Create a list of tool names for the tools provided
|
116 |
+
kwargs["tool_names"] = ", ".join([tool.name for tool in self.tools])
|
117 |
+
kwargs["today"] = date.today()
|
118 |
+
final_prompt = self.template.format(**kwargs)
|
119 |
+
self.ialogger.add_system({"value": final_prompt})
|
120 |
+
return final_prompt
|
121 |
+
|
122 |
+
|
123 |
+
class CustomOutputParser(AgentOutputParser):
|
124 |
+
class Config:
|
125 |
+
arbitrary_types_allowed = True
|
126 |
+
ialogger: InteractionsLogger
|
127 |
+
cred: OpenAICred
|
128 |
+
new_action_input: Optional[str]
|
129 |
+
|
130 |
+
action_history = defaultdict(set)
|
131 |
+
|
132 |
+
def parse(self, llm_output: str) -> Union[AgentAction, AgentFinish]:
|
133 |
+
self.ialogger.add_ai(llm_output)
|
134 |
+
# Check if agent should finish
|
135 |
+
if "Final Answer:" in llm_output:
|
136 |
+
final_answer = llm_output.split("Final Answer:")[-1].strip()
|
137 |
+
self.ialogger.add_structured_data({"output": {"action": "Final Answer",
|
138 |
+
"action_input": final_answer,
|
139 |
+
"raw_output": llm_output}})
|
140 |
+
return AgentFinish(
|
141 |
+
# Return values is generally always a dictionary with a single `output` key
|
142 |
+
# It is not recommended to try anything else at the moment :)
|
143 |
+
return_values={"output": final_answer},
|
144 |
+
log=llm_output,
|
145 |
+
)
|
146 |
+
# Parse out the action and action input
|
147 |
+
regex = r"Action\s*\d*\s*:(.*?)\nAction\s*\d*\s*Input\s*\d*\s*:[\s]*(.*)"
|
148 |
+
match = re.search(regex, llm_output, re.DOTALL)
|
149 |
+
if not match:
|
150 |
+
raise ValueError(f"Could not parse LLM output: `{llm_output}`")
|
151 |
+
action = match.group(1).strip()
|
152 |
+
action_input = match.group(2).strip().strip('"')
|
153 |
+
|
154 |
+
if action_input in self.action_history[action]:
|
155 |
+
new_action_input = rewrite_search_query(action_input,
|
156 |
+
self.action_history[action],
|
157 |
+
cred)
|
158 |
+
self.ialogger.add_message({"query_rewrite": True})
|
159 |
+
self.new_action_input = new_action_input
|
160 |
+
self.action_history[action].add(new_action_input)
|
161 |
+
return AgentAction(tool=action, tool_input=new_action_input, log=llm_output)
|
162 |
+
else:
|
163 |
+
# Return the action and action input
|
164 |
+
self.action_history[action].add(action_input)
|
165 |
+
return AgentAction(tool=action, tool_input=action_input, log=llm_output)
|
166 |
+
|
167 |
+
|
168 |
+
class ActionRunner:
|
169 |
+
def __init__(self,
|
170 |
+
outputq,
|
171 |
+
cred: OpenAICred,
|
172 |
+
model_name: str,
|
173 |
+
persist_logs: bool = False):
|
174 |
+
self.ialogger = InteractionsLogger(name=f"{uuid.uuid4().hex[:6]}", persist=persist_logs)
|
175 |
+
tools = [search_tool, note_tool]
|
176 |
+
prompt = CustomPromptTemplate(
|
177 |
+
template=template,
|
178 |
+
tools=tools,
|
179 |
+
input_variables=["input", "intermediate_steps"],
|
180 |
+
ialogger=self.ialogger)
|
181 |
+
|
182 |
+
output_parser = CustomOutputParser(ialogger=self.ialogger, cred=cred)
|
183 |
+
|
184 |
+
class MyCustomHandler(AsyncCallbackHandler):
|
185 |
+
def __init__(self):
|
186 |
+
pass
|
187 |
+
|
188 |
+
async def on_chain_end(self, outputs, **kwargs) -> None:
|
189 |
+
if "text" in outputs:
|
190 |
+
await outputq.put(outputs["text"])
|
191 |
+
|
192 |
+
async def on_agent_action(
|
193 |
+
self,
|
194 |
+
action: AgentAction,
|
195 |
+
*,
|
196 |
+
run_id: uuid.UUID,
|
197 |
+
parent_run_id: Optional[uuid.UUID] = None,
|
198 |
+
**kwargs: Any,
|
199 |
+
) -> None:
|
200 |
+
if (new_action_input := output_parser.new_action_input):
|
201 |
+
# Notify users
|
202 |
+
await outputq.put(RuntimeWarning(f"Action Input Rewritten: {new_action_input}"))
|
203 |
+
output_parser.new_action_input = None
|
204 |
+
|
205 |
+
async def on_tool_start(
|
206 |
+
self,
|
207 |
+
serialized: Dict[str, Any],
|
208 |
+
input_str: str,
|
209 |
+
*,
|
210 |
+
run_id: uuid.UUID,
|
211 |
+
parent_run_id: Optional[uuid.UUID] = None,
|
212 |
+
**kwargs: Any,
|
213 |
+
) -> None:
|
214 |
+
pass
|
215 |
+
|
216 |
+
async def on_tool_end(
|
217 |
+
self,
|
218 |
+
output: str,
|
219 |
+
*,
|
220 |
+
run_id: uuid.UUID,
|
221 |
+
parent_run_id: Optional[uuid.UUID] = None,
|
222 |
+
**kwargs: Any,
|
223 |
+
) -> None:
|
224 |
+
await outputq.put(output)
|
225 |
+
|
226 |
+
handler = MyCustomHandler()
|
227 |
+
|
228 |
+
llm = ChatOpenAI(openai_api_key=cred.key,
|
229 |
+
openai_organization=cred.org,
|
230 |
+
temperature=0,
|
231 |
+
model_name=model_name)
|
232 |
+
llm_chain = LLMChain(llm=llm, prompt=prompt, callbacks=[handler])
|
233 |
+
tool_names = [tool.name for tool in tools]
|
234 |
+
for tool in tools:
|
235 |
+
tool.callbacks = [handler]
|
236 |
+
|
237 |
+
agent = LLMSingleActionAgent(
|
238 |
+
llm_chain=llm_chain,
|
239 |
+
output_parser=output_parser,
|
240 |
+
stop=["\nObservation:"],
|
241 |
+
allowed_tools=tool_names
|
242 |
+
)
|
243 |
+
callback_manager = AsyncCallbackManager([handler])
|
244 |
+
|
245 |
+
# Finally create the Executor
|
246 |
+
self.agent_executor = AgentExecutor.from_agent_and_tools(agent=agent,
|
247 |
+
tools=tools,
|
248 |
+
verbose=False,
|
249 |
+
callback_manager=callback_manager)
|
250 |
+
|
251 |
+
async def run(self, goal: str, outputq):
|
252 |
+
self.ialogger.set_goal(goal)
|
253 |
+
try:
|
254 |
+
with get_openai_callback() as cb:
|
255 |
+
output = await self.agent_executor.arun(goal)
|
256 |
+
self.ialogger.add_cost({"total_tokens": cb.total_tokens,
|
257 |
+
"prompt_tokens": cb.prompt_tokens,
|
258 |
+
"completion_tokens": cb.completion_tokens,
|
259 |
+
"total_cost": cb.total_cost,
|
260 |
+
"successful_requests": cb.successful_requests})
|
261 |
+
self.ialogger.save()
|
262 |
+
except Exception as e:
|
263 |
+
self.ialogger.add_message({"error": str(e)})
|
264 |
+
self.ialogger.save()
|
265 |
+
await outputq.put(e)
|
266 |
+
return
|
267 |
+
return output
|
autoagents/spaces/app.py
ADDED
@@ -0,0 +1,145 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import asyncio
|
3 |
+
import random
|
4 |
+
from datetime import date, datetime, timezone, timedelta
|
5 |
+
from ast import literal_eval
|
6 |
+
|
7 |
+
import streamlit as st
|
8 |
+
import openai
|
9 |
+
|
10 |
+
from autoagents.utils.constants import MAIN_HEADER, MAIN_CAPTION, SAMPLE_QUESTIONS
|
11 |
+
from autoagents.agents.search import ActionRunner
|
12 |
+
from autoagents.utils.utils import OpenAICred
|
13 |
+
|
14 |
+
async def run():
|
15 |
+
output_acc = ""
|
16 |
+
st.session_state["random"] = random.randint(0, 99)
|
17 |
+
if "task" not in st.session_state:
|
18 |
+
st.session_state.task = None
|
19 |
+
if "model_name" not in st.session_state:
|
20 |
+
st.session_state.model_name = "gpt-3.5-turbo"
|
21 |
+
|
22 |
+
st.set_page_config(
|
23 |
+
page_title="Search Agent",
|
24 |
+
page_icon="🤖",
|
25 |
+
layout="wide",
|
26 |
+
initial_sidebar_state="expanded",
|
27 |
+
)
|
28 |
+
|
29 |
+
st.title(MAIN_HEADER)
|
30 |
+
st.caption(MAIN_CAPTION)
|
31 |
+
|
32 |
+
with st.form("my_form", clear_on_submit=False):
|
33 |
+
st.markdown("<style> .inter { white-space: pre-line; } </style>", unsafe_allow_html=True)
|
34 |
+
user_input = st.text_input(
|
35 |
+
"You: ",
|
36 |
+
key="input",
|
37 |
+
placeholder="Ask me anything ...",
|
38 |
+
label_visibility="hidden",
|
39 |
+
)
|
40 |
+
|
41 |
+
submitted = st.form_submit_button(
|
42 |
+
"Search", help="Hit to submit the search query."
|
43 |
+
)
|
44 |
+
|
45 |
+
# Ask the user to enter their OpenAI API key
|
46 |
+
if (api_key := st.sidebar.text_input("OpenAI api-key", type="password")):
|
47 |
+
cred = OpenAICred(api_key, None)
|
48 |
+
else:
|
49 |
+
cred = OpenAICred(os.getenv("OPENAI_API_KEY"),
|
50 |
+
os.getenv("OPENAI_API_ORG"))
|
51 |
+
with st.sidebar:
|
52 |
+
model_dict = {
|
53 |
+
"gpt-3.5-turbo": "GPT-3.5-turbo",
|
54 |
+
"gpt-4": "GPT-4 (Better but slower)",
|
55 |
+
}
|
56 |
+
st.radio(
|
57 |
+
"OpenAI model",
|
58 |
+
model_dict.keys(),
|
59 |
+
key="model_name",
|
60 |
+
format_func=lambda x: model_dict[x],
|
61 |
+
)
|
62 |
+
|
63 |
+
time_zone = str(datetime.now(timezone(timedelta(0))).astimezone().tzinfo)
|
64 |
+
st.markdown(f"**The system time zone is {time_zone} and the date is {date.today()}**")
|
65 |
+
|
66 |
+
st.markdown("**Example Queries:**")
|
67 |
+
for q in SAMPLE_QUESTIONS:
|
68 |
+
st.markdown(f"*{q}*")
|
69 |
+
|
70 |
+
if not cred.key:
|
71 |
+
st.warning(
|
72 |
+
"API key required to try this app. The API key is not stored in any form. [This](https://help.openai.com/en/articles/4936850-where-do-i-find-my-secret-api-key) might help."
|
73 |
+
)
|
74 |
+
else:
|
75 |
+
outputq = asyncio.Queue()
|
76 |
+
runner = ActionRunner(
|
77 |
+
outputq,
|
78 |
+
cred=cred,
|
79 |
+
model_name=st.session_state.model_name,
|
80 |
+
persist_logs=True,
|
81 |
+
) # log to HF-dataset
|
82 |
+
|
83 |
+
async def cleanup(e):
|
84 |
+
st.error(e)
|
85 |
+
await st.session_state.task
|
86 |
+
st.session_state.task = None
|
87 |
+
st.stop()
|
88 |
+
|
89 |
+
placeholder = st.empty()
|
90 |
+
|
91 |
+
if user_input and submitted:
|
92 |
+
if st.session_state.task is not None:
|
93 |
+
with placeholder.container():
|
94 |
+
st.session_state.task.cancel()
|
95 |
+
st.warning("Previous search aborted", icon="⚠️")
|
96 |
+
|
97 |
+
st.session_state.task = asyncio.create_task(
|
98 |
+
runner.run(user_input, outputq)
|
99 |
+
)
|
100 |
+
iterations = 0
|
101 |
+
with st.expander("Search Results", expanded=True):
|
102 |
+
while True:
|
103 |
+
with st.spinner("Wait for it..."):
|
104 |
+
output = await outputq.get()
|
105 |
+
placeholder.empty()
|
106 |
+
if isinstance(output, Exception):
|
107 |
+
if isinstance(output, openai.error.AuthenticationError):
|
108 |
+
await cleanup(f"AuthenticationError: Invalid OpenAI API key.")
|
109 |
+
elif isinstance(output, openai.error.OpenAIError):
|
110 |
+
await cleanup(output)
|
111 |
+
elif isinstance(output, RuntimeWarning):
|
112 |
+
st.warning(output)
|
113 |
+
continue
|
114 |
+
else:
|
115 |
+
await cleanup("Something went wrong. Please try searching again.")
|
116 |
+
return
|
117 |
+
try:
|
118 |
+
output_fmt = literal_eval(output)
|
119 |
+
st.json(output_fmt, expanded=False)
|
120 |
+
st.write("---")
|
121 |
+
iterations += 1
|
122 |
+
except:
|
123 |
+
output_acc += "\n" + output
|
124 |
+
st.markdown(f"<div class=\"inter\"> {output} </div>",
|
125 |
+
unsafe_allow_html=True)
|
126 |
+
if iterations >= runner.agent_executor.max_iterations:
|
127 |
+
await cleanup(
|
128 |
+
f"Maximum iterations ({iterations}) exceeded. You can try running the search again or try a variation of the query."
|
129 |
+
)
|
130 |
+
return
|
131 |
+
if "Final Answer:" in output:
|
132 |
+
break
|
133 |
+
# Found the answer
|
134 |
+
final_answer = await st.session_state.task
|
135 |
+
final_answer = final_answer.replace("$", "\$")
|
136 |
+
# st.success accepts md
|
137 |
+
st.success(final_answer, icon="✅")
|
138 |
+
st.balloons()
|
139 |
+
st.session_state.task = None
|
140 |
+
st.stop()
|
141 |
+
|
142 |
+
if __name__ == "__main__":
|
143 |
+
loop = asyncio.new_event_loop()
|
144 |
+
loop.set_debug(enabled=False)
|
145 |
+
loop.run_until_complete(run())
|
autoagents/tools/__init__.py
ADDED
File without changes
|
autoagents/tools/tools.py
ADDED
@@ -0,0 +1,70 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
|
3 |
+
from duckpy import Client
|
4 |
+
from langchain import PromptTemplate, OpenAI, LLMChain
|
5 |
+
from langchain.agents import Tool
|
6 |
+
from langchain.chat_models import ChatOpenAI
|
7 |
+
|
8 |
+
from autoagents.utils.utils import OpenAICred
|
9 |
+
|
10 |
+
|
11 |
+
MAX_SEARCH_RESULTS = 20 # Number of search results to observe at a time
|
12 |
+
|
13 |
+
search_description = """ Useful for when you need to ask with search. Use direct language and be
|
14 |
+
EXPLICIT in what you want to search.
|
15 |
+
|
16 |
+
## Examples of incorrect use
|
17 |
+
1. Action: Search
|
18 |
+
Action Input: "[name of bagel shop] menu"
|
19 |
+
|
20 |
+
The Action Input cannot be None or empty.
|
21 |
+
"""
|
22 |
+
|
23 |
+
notepad_description = """ Useful for when you need to note-down specific
|
24 |
+
information for later reference. Please provide full information you want to
|
25 |
+
note-down in the Action Input and all future prompts will remember it.
|
26 |
+
This is the mandatory tool after using the search tool.
|
27 |
+
Using Notepad does not always lead to a final answer.
|
28 |
+
|
29 |
+
## Exampels of using notepad tool
|
30 |
+
Action: Notepad
|
31 |
+
Action Input: the information you want to note-down
|
32 |
+
"""
|
33 |
+
|
34 |
+
async def ddg(query: str):
|
35 |
+
if query is None or query.lower().strip().strip('"') == "none" or query.lower().strip().strip('"') == "null":
|
36 |
+
x = "The action input field is empty. Please provide a search query."
|
37 |
+
return [x]
|
38 |
+
else:
|
39 |
+
client = Client()
|
40 |
+
return client.search(query)[:MAX_SEARCH_RESULTS]
|
41 |
+
|
42 |
+
|
43 |
+
async def notepad(x: str) -> str:
|
44 |
+
return f"{[x]}"
|
45 |
+
|
46 |
+
|
47 |
+
search_tool = Tool(name="Search",
|
48 |
+
func=lambda x: x,
|
49 |
+
coroutine=ddg,
|
50 |
+
description=search_description)
|
51 |
+
|
52 |
+
note_tool = Tool(name="Notepad",
|
53 |
+
func=lambda x: x,
|
54 |
+
coroutine=notepad,
|
55 |
+
description=notepad_description)
|
56 |
+
|
57 |
+
|
58 |
+
def rewrite_search_query(q: str, search_history, cred: OpenAICred) -> str:
|
59 |
+
history_string = '\n'.join(search_history)
|
60 |
+
template ="""We are using the Search tool.
|
61 |
+
# Previous queries:
|
62 |
+
{history_string}. \n\n Rewrite query {action_input} to be
|
63 |
+
different from the previous ones."""
|
64 |
+
llm = ChatOpenAI(temperature=0,
|
65 |
+
openai_api_key=cred.key,
|
66 |
+
openai_organization=cred.org)
|
67 |
+
prompt = PromptTemplate(template=template,
|
68 |
+
input_variables=["action_input", "history_string"])
|
69 |
+
llm_chain = LLMChain(prompt=prompt, llm=llm)
|
70 |
+
return llm_chain.predict(action_input=q, history_string=history_string)
|
autoagents/utils/__init__.py
ADDED
File without changes
|
autoagents/utils/constants.py
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
MAIN_HEADER = "Web Search Agent"
|
2 |
+
|
3 |
+
MAIN_CAPTION = """This is a proof-of-concept search agent that reasons, plans,
|
4 |
+
and executes web searches to collect information on your behalf. It aims to
|
5 |
+
resolve your question by breaking it down into step-by-step subtasks. All the
|
6 |
+
intermediate results will be presented.
|
7 |
+
|
8 |
+
*DISCLAIMER*: We are collecting search queries, so please refrain from
|
9 |
+
providing any personal information. If you wish to avoid this, you can run the
|
10 |
+
app locally by following the instructions on our
|
11 |
+
[Github](https://github.com/AutoLLM/AutoAgents)."""
|
12 |
+
|
13 |
+
SAMPLE_QUESTIONS = [
|
14 |
+
"Recommend me a movie in theater now to watch with kids.",
|
15 |
+
"Who is the most recent NBA MVP? Which team does he play for? What are his career stats?",
|
16 |
+
"Who is the head coach of AC Milan now? How long has he been coaching the team?",
|
17 |
+
"What is the mortgage rate right now and how does that compare to the past two years?",
|
18 |
+
"What is the weather like in San Francisco today? What about tomorrow?",
|
19 |
+
"When and where is the upcoming concert for Taylor Swift? Share a link to purchase tickets.",
|
20 |
+
"Find me recent studies focusing on hallucination in large language models. Provide the link to each study found.",
|
21 |
+
]
|
autoagents/utils/logger.py
ADDED
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import json
|
3 |
+
from typing import Dict, Any
|
4 |
+
import uuid
|
5 |
+
from datetime import datetime
|
6 |
+
import pytz
|
7 |
+
|
8 |
+
import huggingface_hub
|
9 |
+
from huggingface_hub import Repository
|
10 |
+
|
11 |
+
|
12 |
+
class InteractionsLogger:
|
13 |
+
def __init__(self, name: str, persist=False):
|
14 |
+
self.persist = persist
|
15 |
+
self.counter = 0
|
16 |
+
self.name = name # unique id
|
17 |
+
HF_TOKEN = os.environ.get("HF_TOKEN")
|
18 |
+
HF_DATASET_REPO_URL = os.environ.get("HF_DATASET_REPO_URL")
|
19 |
+
if (HF_TOKEN is not None) and (HF_DATASET_REPO_URL is not None):
|
20 |
+
self.repo = Repository(
|
21 |
+
local_dir="data", clone_from=HF_DATASET_REPO_URL, use_auth_token=HF_TOKEN
|
22 |
+
)
|
23 |
+
else:
|
24 |
+
self.persist = False
|
25 |
+
|
26 |
+
def set_goal(self, goal: str):
|
27 |
+
# Initialize two variables for saving two files (self.messages for
|
28 |
+
# training and self.structure_data for later use)
|
29 |
+
self.messages = [{"goal": goal}]
|
30 |
+
self.structured_data = {"goal": goal}
|
31 |
+
|
32 |
+
def add_system(self, more: Dict):
|
33 |
+
self.convos = [{"from": "system"} | more]
|
34 |
+
|
35 |
+
def add_ai(self, msg: str):
|
36 |
+
self.convos.append({"from": "ai", "value": msg})
|
37 |
+
self.messages.append({"id": f"{self.name}_{self.counter}", "conversations": self.convos})
|
38 |
+
self.counter += 1
|
39 |
+
|
40 |
+
def add_structured_data(self, data: Dict[str, Any]):
|
41 |
+
self.structured_data.update({f"turn_{self.counter}": data})
|
42 |
+
|
43 |
+
def add_message(self, data: Dict[str, Any]):
|
44 |
+
self.structured_data.update(data)
|
45 |
+
|
46 |
+
def save(self):
|
47 |
+
# add current datetime
|
48 |
+
self.add_message({"datetime": datetime.now(pytz.utc).strftime("%m/%d/%Y %H:%M:%S %Z%z")})
|
49 |
+
if self.persist:
|
50 |
+
# TODO: want to add retry in a loop?
|
51 |
+
self.repo.git_pull()
|
52 |
+
fname = uuid.uuid4().hex[:16]
|
53 |
+
with open(f"./data/{fname}.json", "w") as f:
|
54 |
+
json.dump(self.messages, f, indent=2)
|
55 |
+
with open(f"./data/{fname}.clean.json", "w") as f:
|
56 |
+
json.dump(self.structured_data, f, indent=2)
|
57 |
+
commit_url = self.repo.push_to_hub()
|
58 |
+
|
59 |
+
def add_cost(self, cost):
|
60 |
+
self.messages.append({"metrics": cost})
|
autoagents/utils/utils.py
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from dataclasses import dataclass
|
2 |
+
from typing import Optional
|
3 |
+
|
4 |
+
|
5 |
+
@dataclass
|
6 |
+
class OpenAICred:
|
7 |
+
key: str
|
8 |
+
org: Optional[str]
|
requirements.txt
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
openai>=0.27.7
|
2 |
+
langchain>=0.0.193
|
3 |
+
duckpy
|
4 |
+
huggingface_hub
|
5 |
+
pytz
|
setup.py
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from setuptools import setup, find_packages
|
2 |
+
|
3 |
+
setup(
|
4 |
+
name='autoagents',
|
5 |
+
version='0.1.0',
|
6 |
+
packages=find_packages(include=['autoagents', 'autoagents.*'])
|
7 |
+
)
|
test.py
ADDED
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import asyncio
|
3 |
+
from autoagents.agents.search import ActionRunner
|
4 |
+
from langchain.callbacks import get_openai_callback
|
5 |
+
from pprint import pprint
|
6 |
+
import pdb
|
7 |
+
from ast import literal_eval
|
8 |
+
from multiprocessing import Pool, TimeoutError
|
9 |
+
|
10 |
+
async def work(user_input):
|
11 |
+
outputq = asyncio.Queue()
|
12 |
+
|
13 |
+
API_O = os.getenv("OPENAI_API_KEY")
|
14 |
+
runner = ActionRunner(outputq, api_key=API_O, model_name="gpt-3.5-turbo")
|
15 |
+
task = asyncio.create_task(runner.run(user_input, outputq))
|
16 |
+
|
17 |
+
while True:
|
18 |
+
output = await outputq.get()
|
19 |
+
if isinstance(output, Exception):
|
20 |
+
print(output)
|
21 |
+
return
|
22 |
+
try:
|
23 |
+
pprint(literal_eval(output))
|
24 |
+
except:
|
25 |
+
print(output)
|
26 |
+
print("-----------------------------------------------------------")
|
27 |
+
if "Final Answer:" in output:
|
28 |
+
break
|
29 |
+
await task
|
30 |
+
|
31 |
+
Q = [
|
32 |
+
"list 5 cities and their current populations where Paramore is playing this year.",
|
33 |
+
"Who is Leo DiCaprio's girlfriend? What is her current age raised to the 0.43 power?",
|
34 |
+
"How many watermelons can fit in a Tesla Model S?",
|
35 |
+
"Recommend me some laptops suitable for UI designers under $2000. Please include brand and price."
|
36 |
+
"Build me a vacation plan for Rome and Milan this summer for seven days. Include place to visit and hotels to stay. ",
|
37 |
+
"What is the sum of ages of the wives of Barack Obama and Donald Trump?",
|
38 |
+
"Who is the most recent NBA MVP? Which team does he play for? What is his season stats?",
|
39 |
+
"What were the scores for the last three games for the Los Angeles Lakers? Provide the dates and opposing teams.",
|
40 |
+
"Which team won in women's volleyball in the Summer Olympics that was held in London?",
|
41 |
+
"Provide a summary of the latest COVID-19 research paper published. Include the title, authors and abstract.",
|
42 |
+
"What is the top grossing movie in theatres this week? Provide the movie title, director, and a brief synopsis of the movie's plot. Attach a review for this movie.",
|
43 |
+
"Recommend a bagel shop near the Strip district in Pittsburgh that offer vegan food",
|
44 |
+
"Who are some top researchers in the field of machine learning systems nowadays?"
|
45 |
+
]
|
46 |
+
|
47 |
+
def main(q):
|
48 |
+
asyncio.run(work(q))
|
49 |
+
|
50 |
+
if __name__ == "__main__":
|
51 |
+
with Pool(processes=10) as pool:
|
52 |
+
print(pool.map(main, Q))
|