105 lines
4.9 KiB
Markdown
105 lines
4.9 KiB
Markdown
# Design Doc: Command-Line Joke Generator
|
|
|
|
> Please DON'T remove notes for AI
|
|
|
|
## Requirements
|
|
|
|
> Notes for AI: Keep it simple and clear.
|
|
> If the requirements are abstract, write concrete user stories
|
|
|
|
The system will be a command-line application that:
|
|
1. Asks the user for a topic for a joke.
|
|
2. Generates a joke based on the provided topic.
|
|
3. Asks the user if they approve of the joke.
|
|
4. If the user approves, the application can end or offer to generate another joke (for simplicity, we'll end for now).
|
|
5. If the user does not approve, the application should:
|
|
a. Take note that the user disliked the previous joke.
|
|
b. Generate a new joke about the same topic, attempting to make it different from the disliked one.
|
|
c. Repeat step 3.
|
|
|
|
## Flow Design
|
|
|
|
> Notes for AI:
|
|
> 1. Consider the design patterns of agent, map-reduce, rag, and workflow. Apply them if they fit.
|
|
> 2. Present a concise, high-level description of the workflow.
|
|
|
|
### Applicable Design Pattern:
|
|
|
|
**Agent**: The system acts as an agent that interacts with the user. It takes user input (topic, feedback), performs an action (generates a joke), and then decides the next step based on user feedback (either end or try generating another joke). This iterative process of generation and feedback fits the agent pattern.
|
|
|
|
### Flow high-level Design:
|
|
|
|
1. **GetTopicNode**: Prompts the user to enter the topic for the joke.
|
|
2. **GenerateJokeNode**: Generates a joke based on the topic and any previous feedback.
|
|
3. **GetFeedbackNode**: Presents the joke to the user and asks for approval. Based on the feedback, it either transitions to end the flow or back to `GenerateJokeNode`.
|
|
|
|
```mermaid
|
|
flowchart TD
|
|
GetTopic[GetTopicNode] --> GenerateJoke[GenerateJokeNode]
|
|
GenerateJoke --> GetFeedback[GetFeedbackNode]
|
|
GetFeedback -- "Approve" --> Z((End))
|
|
GetFeedback -- "Disapprove" --> GenerateJoke
|
|
```
|
|
## Utility Functions
|
|
|
|
> Notes for AI:
|
|
> 1. Understand the utility function definition thoroughly by reviewing the doc.
|
|
> 2. Include only the necessary utility functions, based on nodes in the flow.
|
|
|
|
1. **Call LLM** (`utils/call_llm.py`)
|
|
* *Input*: `prompt` (str), potentially including context like previously disliked jokes.
|
|
* *Output*: `response` (str) - the generated joke.
|
|
* *Necessity*: Used by `GenerateJokeNode` to generate jokes.
|
|
|
|
## Node Design
|
|
|
|
### Shared Store
|
|
|
|
> Notes for AI: Try to minimize data redundancy
|
|
|
|
The shared store structure is organized as follows:
|
|
|
|
```python
|
|
shared = {
|
|
"topic": None, # Stores the user-provided joke topic
|
|
"current_joke": None, # Stores the most recently generated joke
|
|
"disliked_jokes": [], # A list to store jokes the user didn't like, for context
|
|
"user_feedback": None # Stores the user's latest feedback (e.g., "approve", "disapprove")
|
|
}
|
|
```
|
|
|
|
### Node Steps
|
|
|
|
> Notes for AI: Carefully decide whether to use Batch/Async Node/Flow.
|
|
|
|
1. **GetTopicNode**
|
|
* *Purpose*: To get the desired joke topic from the user.
|
|
* *Type*: Regular
|
|
* *Steps*:
|
|
* `prep`: (None needed for the first run, or could check if a topic already exists if we were to loop for a new topic)
|
|
* `exec`: Prompt the user via `input()` for a joke topic.
|
|
* `post`: Store the user's input topic into `shared["topic"]`. Return `"default"` action to proceed to `GenerateJokeNode`.
|
|
|
|
2. **GenerateJokeNode**
|
|
* *Purpose*: To generate a joke using an LLM, based on the topic and any previously disliked jokes.
|
|
* *Type*: Regular
|
|
* *Steps*:
|
|
* `prep`: Read `shared["topic"]` and `shared["disliked_jokes"]`. Construct a prompt for the LLM, including the topic and a message like "The user did not like the following jokes: [list of disliked jokes]. Please generate a new, different joke about [topic]."
|
|
* `exec`: Call the `call_llm` utility function with the prepared prompt.
|
|
* `post`: Store the generated joke in `shared["current_joke"]`. Print the joke to the console. Return `"default"` action to proceed to `GetFeedbackNode`.
|
|
|
|
3. **GetFeedbackNode**
|
|
* *Purpose*: To get feedback from the user about the generated joke and decide the next step.
|
|
* *Type*: Regular
|
|
* *Steps*:
|
|
* `prep`: Read `shared["current_joke"]`.
|
|
* `exec`: Prompt the user (e.g., "Did you like this joke? (yes/no) or (approve/disapprove): "). Get user's input.
|
|
* `post`:
|
|
* If user input indicates approval (e.g., "yes", "approve"):
|
|
* Store "approve" in `shared["user_feedback"]`.
|
|
* Return `"Approve"` action (leading to flow termination or a thank you message).
|
|
* If user input indicates disapproval (e.g., "no", "disapprove"):
|
|
* Store "disapprove" in `shared["user_feedback"]`.
|
|
* Add `shared["current_joke"]` to the `shared["disliked_jokes"]` list.
|
|
* Return `"Disapprove"` action (leading back to `GenerateJokeNode`).
|