Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updates of InteRecAgent #46

Merged
merged 4 commits into from
May 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 53 additions & 25 deletions InteRecAgent/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,48 +59,43 @@ InteRecAgent consists of 4 necessary components:
First, install other packages listed in `requirements.txt`

```bash
cd LLM4CRS
conda create -n llm4crs python==3.9
conda activate llm4crs
cd InteRecAgent
conda create -n interecagent python==3.9
conda activate interecagent
pip install -r requirements.txt
```

2. Copy resource
2. Prepare data resource

Copy all files in "InteRecAgent/{domain}" in [OneDrive](https://1drv.ms/f/s!Asn0lWVfky4FpF3saprFClmobx8g?e=lgeT0M) / [RecDrive](https://rec.ustc.edu.cn/share/baa4d930-48e1-11ee-b20c-3fee0ba82bbd) to your local "./LLM4CRS/resources/{domain}".
If you cannot access those links, please contact <a href="mailto:[email protected]">[email protected]</a> or <a href="mailto:[email protected]">[email protected]</a>.
For your convenience, a volunteer (thanks <a href="mailto:[email protected]">Xu Huang</a> for the contribution!) has prepared a copy of ready-to-run data resources based on public dataset. Please download the resources from [GoogleDrive](https://drive.google.com/file/d/1nSw2cuoi_WEOnHRg_eIyLWGBAjHdelsg/view?usp=drive_link) / [RecDrive](https://rec.ustc.edu.cn/share/baa4d930-48e1-11ee-b20c-3fee0ba82bbd). After you unzip the all_resources.zip file, you will see three folders, corresponding to three domains. Create a folder named "resources" under "InteRecAgent" and copy the data resource to it. For example, the folder structure is like "./InteRecAgent/resources/game".

3. Run
3. How to run

- Personal OpenAI API key:
- If you are using personal OpenAI API, please setup those environments:

```bash
cd LLM4CRS
DOMAIN="game" OPENAI_API_KEY="xxxx" python app.py
export OPENAI_API_KEY="xxxx"
export API_TYPE="open_ai"
```

- Azure OpenAI API key:
- If you are using Azure OpenAI API, please setup those environments:


```bash
cd LLM4CRS
DOMAIN="game" OPENAI_API_KEY="xxx" OPENAI_API_BASE="xxx" OPENAI_API_VERSION="xxx" OPENAI_API_TYPE="xxx" python app.py
export OPENAI_API_KEY="xxx"
export OPENAI_API_BASE="xxx"
export OPENAI_API_VERSION="xxx"
export OPENAI_API_TYPE="azure"
```

Note `DOMAIN` represents the item domain, supported `game`, `movie` and `beauty_product` now.

We support two types of OpenAI API: [Chat](https://platform.openai.com/docs/api-reference/chat) and [Completions](https://platform.openai.com/docs/api-reference/completions). Here are commands for running RecBot with GPT-3.5-turbo and text-davinci-003.

```bash
cd LLMCRS

# Note that the engine should be your deployment id
# completion type: text-davinci-003
OPENAI_API_KEY="xxx" [OPENAI_API_BASE="xxx" OPENAI_API_VERSION="xxx" OPENAI_API_TYPE="xxx"] python app.py --engine text-davinci-003 --bot_type completion
Then, you can launch the app with:

# chat type: gpt-3.5-turbo, gpt-4 (Recommended)
OPENAI_API_KEY="xxx" [OPENAI_API_BASE="xxx" OPENAI_API_VERSION="xxx" OPENAI_API_TYPE="xxx"] python app.py --engine gpt-3.5-turbo/gpt-4 --bot_type chat
```bash
DOMAIN=game python app.py --engine gpt-4
```

Note that `DOMAIN` represents the item domain, e.g., `game`, `movie` and `beauty_product` in the provided data sources. Replace `gpt-4` with your own deploy name when using Azure OpenAI API.

We also provide a shell script `run.sh`, where commonly used arguments are given. You could directly set the API related information in `run.sh`, or create a new shell script `oai.sh` that would be loaded in `run.sh`. GPT-4 API is highly recommended for the InteRecAgent since it has remarkable instruction-following capability.

Here is an example of the `oai.sh` script:
Expand All @@ -114,6 +109,39 @@ InteRecAgent consists of 4 necessary components:
bot_type="chat" # model type, ["chat", "completetion"]. For gpt-3.5-turbo and gpt-4, it should be "chat". For text-davinci-003, it should be "completetion"
```

Meanwhile, we support to serve local models such as Vicuna as the backbone language model instead of OpenAI APIs:

1. Download the weights of [Vicuna](https://huggingface.co/lmsys/vicuna-7b-v1.5) from huggingface.

2. Install `fschat` package according to [FastChat](https://github.com/lm-sys/FastChat?tab=readme-ov-file#install)

3. Deploy the Vicuna model with OpenAI-Compatible RESTful APIs by running the following command:

```bash
# First, launch the controller
python3 -m fastchat.serve.controller
# Then, launch the model worker(s)
python3 -m fastchat.serve.model_worker --model-path path-to-vicuna
# Finally, launch the RESTful API server
python3 -m fastchat.serve.openai_api_server --host localhost --port 8000
```

4. Set the configuration for RecLlama API in `run.sh`

```bash
API_KEY="EMPTY"
API_BASE="http://localhost:8000/v1"
API_VERSION="2023-03-15-preview"
API_TYPE="open_ai"
engine="vicuna-7b-v1.5" # model name
bot_type="completetion" # model type
```

5. Run the `run.sh` script to start the chatbot.


Also, we support to use our finetuned model RecLlama as the backbone language model, the tutorial could be found in [RecLlama](./RecLlama.md).


4. Features

Expand Down
11 changes: 7 additions & 4 deletions InteRecAgent/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
parser.add_argument(
"--bot_type",
type=str,
default="completion",
default="chat",
choices=["chat", "completion"],
help="Type OpenAI models. The default is completion. Options [completion, chat]",
)
Expand All @@ -73,14 +73,17 @@
"--demo_mode",
type=str,
choices=["zero", "fixed", "dynamic"],
default="zero",
default="dynamic",
help="Directory path of demonstrations",
)
parser.add_argument(
"--demo_dir_or_file", type=str, help="Directory or file path of demonstrations"
"--demo_dir_or_file",
type=str,
default="./demonstration/seed_demos_placeholder.jsonl",
help="Directory or file path of demonstrations"
)
parser.add_argument(
"--num_demos", type=int, default=3, help="number of demos for in-context learning"
"--num_demos", type=int, default=5, help="number of demos for in-context learning"
)

# reflection mechanism
Expand Down
1 change: 1 addition & 0 deletions InteRecAgent/demonstration/seed_demos.jsonl
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@
{"request": "I have played Rust and Portal, which game suit me most in the recommendation list?", "plan": "1. candidate store tool (store games in recommendation list as candidates); 2. ranking tool (rank the candidates according to play history); 3. map tool"}
{"request": "I have played NBA2K, refine the recommendation list for me.", "plan": "1. candidate store tool (store games in recommendation list as candidates); 2. ranking tool (rank the candidates according to play history); 3. map tool"}
{"request": "Which games are first-person in above list?", "plan": "1. candidate store tool (store games in above list as candidates); 2. hard condition tool (filter first-person games from candidates); 3. map tool"}
{"request": "I want some puzzle games, such as Sudoku, do you have any suggestions?", "plan": "1. hard condition tool (filter puzzle games from candidates); 2. soft condition tool (similar to Sudoku); 3. map tool"}
14 changes: 14 additions & 0 deletions InteRecAgent/demonstration/seed_demos_placeholder.jsonl
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{"request": "I want some TAG games.", "plan": "1. hard condition filter tool (for TAG games); 2. ranking tool (by popularity); 3. map tool"}
{"request": "I have played a lot of TAG games, like GAME1, GAME2, GAME3, GAME4. GAME3 is my favorite games, but GAME1 and GAME2 make me disgusted. Can you recommend some popular games released after 2016, similar with GAME4?", "plan": "1. hard condition filter tool (released after 2016); 2. soft condition filter tool (similar with GAME4); 3. ranking tool (user history: GAME1, GAME2, GAME3, GAME4; user unwants GAME1 and GAME2); 4. map tool"}
{"request": "I have played GAME1 and GAME2 in the past, please suggest me some games.", "plan": "1. ranking tool (user history GAME1 and GAME2, by preference); 2. map tool"}
{"request": "I am looking for some games similar to GAME, do you have any suggestions?", "plan": "1. soft condition filter tool (similar to GAME); 2. ranking tool (by similarity); 3. map tool"}
{"request": "Give me some TAG1 or TAG2 games, but I don't like TAG3 games.", "plan": "1. hard condition filter tool (TAG1 or TAG2 games, not TAG3 games); 2. ranking tool (by popularity); 3. map tool"}
{"request": "I'm looking for some TAG games like GAME, but I want a cheaper one.", "plan": "1. look up tool (price of GAME); 2. hard condition filter tool (TAG games, cheaper than the price of GAME); 2. soft condition filter tool (similar to GAME); 3. ranking tool (by similarity); 4. map tool"}
{"request": "I used to play GAME1 and GAME2, but now I feel bored of them. Please give 3 some new games.", "plan": "1. hard condition filter tool (released in recent years); 2. ranking tool (user has played GAME1 and GAME2, user doesn't want the two games; by preference); 3. map tool"}
{"request": "I want some TAG games to play, but I don't like GAME1 and GAME2.", "plan": "1. hard condition filter tool (TAG games); 2. ranking tool (user unwants GAME1 and GAME2; by preference); 3. map tool"}
{"request": "Please give me details about the game GAME.", "plan": "1. look up tool (game description about GAME)"}
{"request": "How much does the game cost?", "plan": "1. look up tool (price of the game)"}
{"request": "I have played GAME1 and GAME2, which game suits me most in the recommendation list?", "plan": "1. candidate store tool (store games in above recommendation list as candidates); 2. ranking tool (rank the candidates according to history: GAME1, GAME2, by preference); 3. map tool"}
{"request": "I have played GAME, refine the recommendation list for me.", "plan": "1. candidate store tool (store games in recommendation list as candidates); 2. ranking tool (rank the candidates according to play history GAME, by preference); 3. map tool"}
{"request": "Which games are TAG in above list?", "plan": "1. candidate store tool (store games in above list as candidates); 2. hard condition tool (filter TAG games from candidates); 3. map tool"}
{"request": "I want some TAG games, such as GAME, do you have any suggestions?", "plan": "1. hard condition tool (filter TAG games from candidates); 2. soft condition tool (similar to GAME); 3. map tool"}
4 changes: 4 additions & 0 deletions InteRecAgent/llm4crs/agent_plan_first_openai.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,8 @@ def __init__(
self.memory = []

def clear(self) -> None:
self._shortened_dialogue_history: str = ""
self._shortened_dialogue_turn: int = 0
self.memory = []

def get(self) -> str:
Expand Down Expand Up @@ -406,6 +408,7 @@ def clear(self):
if self._record_planning:
self._plan_record_cache = {"traj": [], "conv": [], "reward": 0}
logger.debug("History Cleared!")
logger.debug("Memory Cleared!")
if self.user_profile:
self.user_profile.clear()

Expand Down Expand Up @@ -513,6 +516,7 @@ def plan_and_exe(self, prompt: str, prompt_map: Dict) -> str:
def _parse_llm_output(self, llm_output: str) -> Tuple[bool, str]:
llm_output = llm_output.strip()

llm_output = llm_output.replace("###", "") # in case of special token
regex = r"Action\s*\d*\s*:(.*?)\nAction\s*\d*\s*Input\s*\d*\s*:[\s]*(.*)"
match = re.search(regex, llm_output, re.DOTALL)
if not match:
Expand Down
38 changes: 17 additions & 21 deletions InteRecAgent/llm4crs/prompt/system.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,32 +56,32 @@

Use the following format to think about whether to use this tool in above order: \

```
###
Question: Do I need to use the tool to process human's input?
Thought: Yes or No. If yes, give Action and Action Input; else skip to next question.
Action: this tool, one from [{BufferStoreTool}, {LookUpTool}, {HardFilterTool}, {SoftFilterTool}, {RankingTool}, {MapTool}]
Action Input: the input to the action
Observation: the result of the action
```
###

If one tool is used, wait for the Observation.

If you know the final answer, use the format:
```
###
Question: Do I need to use tool to process human's input?
Thought: No, I now know the final answer
Final Answer: the final answer to the original input question
```
###

Either `Final Answer` or `Action` must appear in one response.

If not need to use tools, use the following format: \

```
###
Question: Do I need to use tool to process human's input?
Thought: No, I know the final answer
Final Answer: the final answer to the original input question
```
###

You are allowed to ask some questions instead of recommend when there is not enough information.
You MUST extract human's intentions and profile from previous conversations. These were previous conversations you completed:
Expand All @@ -106,11 +106,11 @@
You are a conversational {item} recommendation assistant. Your task is to help human find {item}s they are interested in. \
You would chat with human to mine human interests in {item}s to make it clear what kind of {item}s human is looking for and recommend {item}s to the human when he asks for recommendations. \

Human requests typically fall under chit-chat, {item} info, or {item} recommendations. There are some tools to use to deal with human request.\
Human requests typically fall under chit-chat, asking for {item} info, or asking for {item} recommendations. There are some tools to use to deal with human request.\
For chit-chat, respond with your knowledge. For {item} info, use the {LookUpTool}. \
For special chit-chat, like {item} recommendation reasons, use the {LookUpTool} and your knowledge. \
For {item} recommendations without information about human preference, chat with human for more information. \
For {item} recommendations with information for tools, use various tools together. \
For {item} recommendations without obvious intention, chat with human for more information. \
For {item} recommendations with information, use various tools to get recommendations. \

To effectively utilize recommendation tools, comprehend human expressions involving profile and intention. \
Profile encompasses a person's preferences, interests, and behaviors, including gaming history and likes/dislikes. \
Expand All @@ -130,10 +130,10 @@

If human is looking up information of {item}s, such as the description of {item}s, number of {item}s, price of {item}s and so on, use the {LookUpTool}. \

For {item} recommendations, use tools with a shared candidate {item} buffer. Buffer is initialized with all {item}s. Filtering tools fetch candidates from the buffer and update it. \
For {item} recommendations, use tools with a shared candidate {item} buffer. Buffer is initialized with all {item}s. Filtering tools fetch candidates from the buffer and update it. Remember to use {HardFilterTool} before {SoftFilterTool} if both are needed. Remember to use {RankingTool} to process human's historical interactions or remove unwanted candidates. \
Ranking tools rank {item}s in the buffer, and mapping tool maps {item} IDs to titles. \
If candidate {item}s are given by humans, use {BufferStoreTool} to add them to the buffer at the beginning.
Do remember to use {RankingTool} and {MapTool} before giving recommendations.
You MUST use {RankingTool} and {MapTool} before giving recommendations.

Think about whether to use tool first. If yes, make tool using plan and give the input of each tool. Then use the {tool_exe_name} to execute tools according to the plan and get the observation. \
Only those tool names are optional when making plans: {tool_names}
Expand All @@ -148,24 +148,20 @@

First you need to think whether to use tools. If no, use the format to output:

```
###
Question: Do I need to use tools to process human's input?
Thought: No, I know the final answer.
Final Answer: the final answer to the original input question
```
Thought: No, I do not need to use tools because I know the final answer (or I need to ask more questions).
Final Answer: the final answer to the original input question (or the question I asked)
###

If use tools, use the format:
```
###
Question: Do I need to use tools to process human's input?
Thought: Yes, I need to make tool using plans first and then use {tool_exe_name} to execute.
Action: {tool_exe_name}
Action Input: the input to {tool_exe_name}, should be a plan
Observation: the result of tool execution

Question: Do I need to use tools to process human's input?
Thought: No, I know the final answer.
Final Answer: the final answer to the original input question
```
###

You are allowed to ask some questions instead of using tools to recommend when there is not enough information.
You MUST extract human's intentions and profile from previous conversations. These were previous conversations you completed:
Expand Down
Loading