Yosef Frost 1 year ago
parent
commit
f38c1cf9a1
  1. 1
      .python-version
  2. 93
      README.md
  3. 5
      installer/client/cli/fabric.py
  4. 6
      installer/client/cli/p.py
  5. 208
      installer/client/cli/utils.py
  6. 11
      patterns/provide_guidance/system.md
  7. 2
      poetry.lock
  8. 4
      pyproject.toml
  9. 67
      setup.sh

1
.python-version

@ -1 +0,0 @@
3.10

93
README.md

@ -26,7 +26,7 @@
## Navigation
- [Introduction Video](#introduction-video)
- [Introduction Videos](#introduction-videos)
- [What and Why](#what-and-why)
- [Philosophy](#philosophy)
- [Breaking problems into components](#breaking-problems-into-components)
@ -48,15 +48,18 @@
<br />
> [!NOTE]
> We are adding functionality to the project so often that you should update often as well. That means: `git pull; ./setup.sh; fabric --update` in the main directory, and then sourcing your shell files and/or restarting your terminal. So exciting!
> We are adding functionality to the project so often that you should update often as well. That means: `git pull; pipx upgrade fabric; fabric --update; source ~/.zshrc (or ~/.bashrc)` in the main directory!
**March 11, 2024** — We just added support for Claude, local models via Ollama, and a number of new Patterns. Be sure to update and check `fabric -h` for the latest!
**March 13, 2024** — We just added `pipx` install support, which makes it way easier to install Fabric, support for Claude, local models via Ollama, and a number of new Patterns. Be sure to update and check `fabric -h` for the latest!
## Introduction video
## Introduction videos
<div align="center">
<a href="https://youtu.be/wPEyyigh10g">
<img width="972" alt="fabric_intro_video" src="https://github.com/danielmiessler/fabric/assets/50654/1eb1b9be-0bab-4c77-8ed2-ed265e8a3435">
<img width="972" alt="fabric_intro_video" src="https://github.com/danielmiessler/fabric/assets/50654/1eb1b9be-0bab-4c77-8ed2-ed265e8a3435"></a>
<br /><br />
<a href="http://www.youtube.com/watch?feature=player_embedded&v=lEXd6TXPw7E target="_blank">
<img src="http://img.youtube.com/vi/lEXd6TXPw7E/mqdefault.jpg" alt="Watch the video" width="972" " />
</a>
</div>
@ -148,40 +151,39 @@ git clone https://github.com/danielmiessler/fabric.git
cd fabric
```
4. Ensure the `setup.sh` script is executable. If you're not sure, you can make it executable by running the following command:
4. Install pipx:
macOS:
```bash
chmod +x setup.sh
brew install pipx
```
5. Install poetry
ref.: https://python-poetry.org/docs/#installing-with-the-official-installer
Linux:
```bash
curl -sSL https://install.python-poetry.org | python3 -
sudo apt intall pipx
```
6. Run the `setup.sh`, which will do the following:
Windows:
Use WSL and follow the Linux instructions.
- Installs python dependencies.
- Creates aliases in your OS. It should update `~/.bashrc`, `/.zshrc`, and `~/.bash_profile` if they are present in your file system.
5. Install fabric
```bash
./setup.sh
pipx install .
```
7. Restart your shell to reload everything.
8. Set your `OPENAI_API_KEY`.
6. Run setup:
```bash
fabric --setup
```
You'll be asked to enter your OpenAI API key, which will be written to `~/.config/fabric/.env`. Patterns will then be downloaded from Github, which will take a few moments.
7. Restart your shell to reload everything.
9. Now you are up and running! You can test by pulling the help.
8. Now you are up and running! You can test by running the help.
```bash
# Making sure the paths are set up correctly
@ -199,45 +201,52 @@ Once you have it all set up, here's how to use it.
`fabric -h`
```bash
fabric [-h] [--text TEXT] [--copy] [--agents {trip_planner,ApiKeys}]
[--output [OUTPUT]] [--stream] [--list] [--clear] [--update]
[--pattern PATTERN] [--setup]
[--changeDefaultModel CHANGEDEFAULTMODEL] [--model MODEL]
[--listmodels] [--context]
An open source framework for augmenting humans using AI.
options:
-h, --help show this help message and exit
--text TEXT, -t TEXT Text to extract summary from
--copy, -C Copy the response to the clipboard
--agents {trip_planner,ApiKeys}, -a {trip_planner,ApiKeys}
Use an AI agent to help you with a task. Acceptable
values are 'trip_planner' or 'ApiKeys'. This option
cannot be used with any other flag.
--output [OUTPUT], -o [OUTPUT]
Save the response to a file
--stream, -s Use this option if you want to see the results in
us the results in
realtime. NOTE: You will not be able to pipe the
output into another command.
--list, -l List available patterns
--clear Clears your persistent model choice so that you can
once again use the --model flag
--update, -u Update patterns
--update, -u Update patterns. NOTE: This will revert the default
model to gpt4-turbo. please run --changeDefaultModel
to once again set default model
--pattern PATTERN, -p PATTERN
The pattern (prompt) to use
--setup Set up your fabric instance
--changeDefaultModel CHANGEDEFAULTMODEL
Change the default model. Your choice will be saved in
~/.config/fabric/.env). For a list of available
Change the default model. For a list of available
models, use the --listmodels flag.
--model MODEL, -m MODEL
Select the model to use. NOTE: Will not work if you
have set a default model. please use --clear to clear
persistence before using this flag
--listmodels List all available models
--remoteOllamaServer REMOTEOLLAMASERVER
The URL of the remote ollamaserver to use. ONLY USE
THIS if you are using a local ollama server in an non-
deault location or port
--context, -c Use Context file (context.md) to add context to your
pattern
age: fabric [-h] [--text TEXT] [--copy] [--agents {trip_planner,ApiKeys}]
[--output [OUTPUT]] [--stream] [--list] [--clear] [--update]
[--pattern PATTERN] [--setup]
[--changeDefaultModel CHANGEDEFAULTMODEL] [--model MODEL]
[--listmodels] [--remoteOllamaServer REMOTEOLLAMASERVER]
[--context]
An open source framework for augmenting humans using AI.
options:
-h, --help show this help message and exit
--text TEXT, -t TEXT Text to extract summary from
--copy, -C Copy the response to the clipboard
--agents {trip_planner,ApiKeys}, -a {trip_planner,ApiKeys}
Use an AI agent to help you with a task. Acceptable
values are 'trip_planner' or 'ApiKeys'. This option
cannot be used with any other flag.
--output [OUTPUT], -o [OUTPUT]
Save the response to a file
--stream, -s Use this option if you want to see
```
#### Example commands

5
installer/client/cli/fabric.py

@ -49,7 +49,7 @@ def main():
help="Change the default model. For a list of available models, use the --listmodels flag.")
parser.add_argument(
"--model", "-m", help="Select the model to use. NOTE: Will not work if you have set a default model. please use --clear to clear persistence before using this flag", default="gpt-4-turbo-preview"
"--model", "-m", help="Select the model to use. NOTE: Will not work if you have set a default model. please use --clear to clear persistence before using this flag"
)
parser.add_argument(
"--listmodels", help="List all available models", action="store_true"
@ -69,7 +69,7 @@ def main():
os.makedirs(config)
if args.setup:
Setup().run()
Alias()
Alias().execute()
sys.exit()
if not os.path.exists(env_file) or not os.path.exists(config_patterns_directory):
print("Please run --setup to set up your API key and download patterns.")
@ -80,7 +80,6 @@ def main():
sys.exit()
if args.changeDefaultModel:
Setup().default_model(args.changeDefaultModel)
print(f"Default model changed to {args.changeDefaultModel}")
sys.exit()
if args.agents:
# Handle the agents logic

6
installer/client/cli/p.py

@ -1,6 +0,0 @@
#!/usr/bin/env python3
import pyperclip
pasted_text = pyperclip.paste()
print(pasted_text)

208
installer/client/cli/utils.py

@ -389,45 +389,15 @@ class Update:
class Alias:
def __init__(self):
self.config_files = []
home_directory = os.path.expanduser("~")
self.patterns = os.path.join(home_directory, ".config/fabric/patterns")
if os.path.exists(os.path.join(home_directory, ".config/fabric/fabric-bootstrap.inc")):
self.config_files.append(os.path.join(
home_directory, ".config/fabric/fabric-bootstrap.inc"))
self.remove_all_patterns()
self.add_patterns()
print('Aliases added successfully. Please restart your terminal to use them.')
def add(self, name, alias):
for file in self.config_files:
with open(file, "a") as f:
f.write(f"alias {name}='{alias}'\n")
def remove(self, pattern):
for file in self.config_files:
# Read the whole file first
with open(file, "r") as f:
wholeFile = f.read()
# Determine if the line to be removed is in the file
target_line = f"alias {pattern}='fabric --pattern {pattern}'\n"
if target_line in wholeFile:
# If the line exists, replace it with nothing (remove it)
wholeFile = wholeFile.replace(target_line, "")
# Write the modified content back to the file
with open(file, "w") as f:
f.write(wholeFile)
def remove_all_patterns(self):
allPatterns = os.listdir(self.patterns)
for pattern in allPatterns:
self.remove(pattern)
def add_patterns(self):
allPatterns = os.listdir(self.patterns)
for pattern in allPatterns:
self.add(pattern, f"fabric --pattern {pattern}")
self.home_directory = os.path.expanduser("~")
patternsFolder = os.path.join(
self.home_directory, ".config/fabric/patterns")
self.patterns = os.listdir(patternsFolder)
def execute(self):
with open(os.path.join(self.home_directory, ".config/fabric/fabric-bootstrap.inc"), "w") as w:
for pattern in self.patterns:
w.write(f"alias {pattern}='fabric --pattern {pattern}'\n")
class Setup:
@ -442,6 +412,14 @@ class Setup:
self.pattern_directory = os.path.join(
self.config_directory, "patterns")
os.makedirs(self.pattern_directory, exist_ok=True)
self.shconfigs = []
home = os.path.expanduser("~")
if os.path.exists(os.path.join(home, ".bashrc")):
self.shconfigs.append(os.path.join(home, ".bashrc"))
if os.path.exists(os.path.join(home, ".bash_profile")):
self.shconfigs.append(os.path.join(home, ".bash_profile"))
if os.path.exists(os.path.join(home, ".zshrc")):
self.shconfigs.append(os.path.join(home, ".zshrc"))
self.env_file = os.path.join(self.config_directory, ".env")
self.gptlist = []
self.fullOllamaList = []
@ -457,6 +435,20 @@ class Setup:
except:
pass
def update_shconfigs(self):
bootstrap_file = os.path.join(
self.config_directory, "fabric-bootstrap.inc")
sourceLine = f'if [ -f "{bootstrap_file}" ]; then . "{bootstrap_file}"; fi'
for config in self.shconfigs:
lines = None
with open(config, 'r') as f:
lines = f.readlines()
with open(config, 'w') as f:
for line in lines:
if sourceLine not in line:
f.write(line)
f.write(sourceLine)
def fetch_available_models(self):
headers = {
"Authorization": f"Bearer {self.openaiapi_key}"
@ -593,96 +585,6 @@ class Setup:
with open(self.env_file, "w") as f:
f.write(f"YOUTUBE_API_KEY={youtube_key}\n")
def update_fabric_command(self, line, model):
fabric_command_regex = re.compile(
r"(alias.*fabric --pattern\s+\S+.*?)( --model.*)?'")
match = fabric_command_regex.search(line)
if match:
base_command = match.group(1)
# Provide a default value for current_flag
current_flag = match.group(2) if match.group(2) else ""
new_flag = ""
new_flag = f" --model {model}"
# Update the command if the new flag is different or to remove an existing flag.
# Ensure to add the closing quote that was part of the original regex
return f"{base_command}{new_flag}'\n"
else:
return line # Return the line unmodified if no match is found.
def update_fabric_alias(self, line, model):
fabric_alias_regex = re.compile(
r"(alias fabric='[^']+?)( --model.*)?'")
match = fabric_alias_regex.search(line)
if match:
base_command, current_flag = match.groups()
new_flag = f" --model {model}"
# Update the alias if the new flag is different or to remove an existing flag.
return f"{base_command}{new_flag}'\n"
else:
return line # Return the line unmodified if no match is found.
def clear_alias(self, line):
fabric_command_regex = re.compile(
r"(alias fabric='[^']+?)( --model.*)?'")
match = fabric_command_regex.search(line)
if match:
base_command = match.group(1)
return f"{base_command}'\n"
else:
return line # Return the line unmodified if no match is found.
def clear_env_line(self, line):
fabric_command_regex = re.compile(
r"(alias.*fabric --pattern\s+\S+.*?)( --model.*)?'")
match = fabric_command_regex.search(line)
if match:
base_command = match.group(1)
return f"{base_command}'\n"
else:
return line # Return the line unmodified if no match is found.
def pattern(self, line):
fabric_command_regex = re.compile(
r"(alias fabric='[^']+?)( --model.*)?'")
match = fabric_command_regex.search(line)
if match:
base_command = match.group(1)
return f"{base_command}'\n"
else:
return line # Return the line unmodified if no match is found.
def clean_env(self):
"""Clear the DEFAULT_MODEL from the environment file.
Returns:
None
"""
user_home = os.path.expanduser("~")
sh_config = None
# Check for shell configuration files
if os.path.exists(os.path.join(user_home, ".config/fabric/fabric-bootstrap.inc")):
sh_config = os.path.join(
user_home, ".config/fabric/fabric-bootstrap.inc")
else:
print("No environment file found.")
if sh_config:
with open(sh_config, "r") as f:
lines = f.readlines()
with open(sh_config, "w") as f:
for line in lines:
modified_line = line
# Update existing fabric commands
if "fabric --pattern" in line:
modified_line = self.clear_env_line(
modified_line)
elif "fabric=" in line:
modified_line = self.clear_alias(
modified_line)
f.write(modified_line)
self.remove_duplicates(env_file)
else:
print("No shell configuration file found.")
def default_model(self, model):
"""Set the default model in the environment file.
@ -700,43 +602,30 @@ class Setup:
# Compile regular expressions outside of the loop for efficiency
user_home = os.path.expanduser("~")
sh_config = None
# Check for shell configuration files
if os.path.exists(os.path.join(user_home, ".config/fabric/fabric-bootstrap.inc")):
sh_config = os.path.join(
user_home, ".config/fabric/fabric-bootstrap.inc")
if sh_config:
with open(sh_config, "r") as f:
if os.path.exists(os.path.expanduser("~/.config/fabric/.env")):
env = os.path.expanduser("~/.config/fabric/.env")
there = False
with open(env, "r") as f:
lines = f.readlines()
with open(sh_config, "w") as f:
for line in lines:
modified_line = line
# Update existing fabric commands
if "fabric --pattern" in line:
modified_line = self.update_fabric_command(
modified_line, model)
elif "fabric=" in line:
modified_line = self.update_fabric_alias(
modified_line, model)
f.write(modified_line)
if "DEFAULT_MODEL" in lines:
there = True
if there:
with open(env, "w") as f:
for line in lines:
modified_line = line
# Update existing fabric commands
if "DEFAULT_MODEL" in line:
modified_line = f'DEFAULT_MODEL={model}\n'
f.write(modified_line)
else:
with open(env, "a") as f:
f.write(f'DEFAULT_MODEL={model}\n')
print(f"""Default model changed to {
model}. Please restart your terminal to use it.""")
else:
print("No shell configuration file found.")
def remove_duplicates(self, filename):
unique_lines = set()
with open(filename, 'r') as file:
lines = file.readlines()
with open(filename, 'w') as file:
for line in lines:
if line not in unique_lines:
file.write(line)
unique_lines.add(line)
def patterns(self):
""" Method to update patterns and exit the system.
@ -769,6 +658,7 @@ class Setup:
youtubekey = input()
self.youtube_key(youtubekey)
self.patterns()
self.update_shconfigs()
class Transcribe:

11
patterns/provide_guidance/system.md

@ -10,23 +10,26 @@ You are an all-knowing psychiatrist, psychologist, and life coach and you provid
- In a section called ONE SENTENCE ANALYSIS AND RECOMMENDATION, give a single sentence that tells them how to approach their situation.
- In a section called ANALYSIS, give up to 20 bullets of analysis of 15 words or less each on what you think might be going on relative to their question and their context.
- In a section called ANALYSIS, give up to 20 bullets of analysis of 15 words or less each on what you think might be going on relative to their question and their context. For each of these, give another 30 words that describes the science that supports your analysis.
- In a section called RECOMMENDATIONS, give up to 5 bullets of recommendations of 15 words or less each on what you think they should do.
- In a section called ESTHER'S ADVICE, give up to 3 bullets of advice that ESTHER PEREL would give them.
- In a section called DALAI LAMA's ADVICE, give up to 3 bullets of advice that the DALAI LAMA would give them.
- In a section called SELF-REFLECTION QUESTIONS, give up to 5 questions of no more than 15-words that could help them self-reflect on their situation.
- In a section called CLINICAL DIAGNOSIS, give up to 5 named disorders that could be at play here. Examples: Co-dependency, PTSD, NPD, Avoidance, etc.
- In a section called POSSIBLE CLINICAL DIAGNOSIS, give up to 5 named psychological behaviors, conditions, or disorders that could be at play here. Examples: Co-dependency, Psychopathy, PTSD, Narcissism, etc.
- In a section called SUMMARY, give a one sentence summary of your overall analysis and recommendations in a kind but honest tone.
- After a "—" and a new line, add a NOTE: saying: "This was produced by an imperfect AI. The best thing to do with this information is to think about it and take it to an actual professional. Don't take it too seriously on its own."
# OUTPUT INSTRUCTIONS
- Output only in Markdown.
- Don't tell me to consult a professional. Just give me your best opinion.
- Do not output bold or italicized text; just basic Markdown.
- Be courageous and honest in your feedback rather than cautious.
# INPUT:

2
poetry.lock

@ -3673,4 +3673,4 @@ testing = ["coverage (>=5.0.3)", "zope.event", "zope.testing"]
[metadata]
lock-version = "2.0"
python-versions = "^3.10"
content-hash = "76e17c74f2e939c22858a9edaea512766a05d0d7737825b13f8b9928cc91e188"
content-hash = "f2995ca96c32fda2c1567d045cb36422b0f5541e809c47e24ff96025a35ac7b0"

4
pyproject.toml

@ -24,6 +24,10 @@ youtube-transcript-api = "^0.6.2"
pydub = "^0.25.1"
ollama = "^0.1.7"
anthropic = "^0.18.1"
pyperclip = "^1.8.2"
python-dotenv = "^1.0.1"
jwt = "^1.3.1"
flask = "^3.0.2"
[tool.poetry.group.cli.dependencies]
pyyaml = "^6.0.1"

67
setup.sh

@ -1,67 +0,0 @@
#!/bin/bash
# Check if pyproject.toml exists in the current directory
if [ ! -f "pyproject.toml" ]; then
echo "Poetry could not find a pyproject.toml file in the current directory or its parents."
echo "Please navigate to the project directory where pyproject.toml is located and rerun this script."
exit 1
fi
# Installs poetry-based python dependencies
echo "Installing python dependencies"
poetry install
# List of commands to check and add or update alias for
# Add 'yt' and 'ts' to the list of commands
commands=("fabric" "fabric-api" "fabric-webui" "ts" "yt")
# Path to the bootstrap file
bootstrap_file="$HOME/.config/fabric/fabric-bootstrap.inc"
# Ensure the directory for the bootstrap file exists
mkdir -p "$(dirname "$bootstrap_file")"
# Start the bootstrap file with a shebang if it doesn't already exist
if [ ! -f "$bootstrap_file" ]; then
echo "#!/bin/bash" > "$bootstrap_file"
fi
# List of shell configuration files to update
config_files=("$HOME/.bashrc" "$HOME/.zshrc" "$HOME/.bash_profile")
for config_file in "${config_files[@]}"; do
# Check if the configuration file exists
if [ -f "$config_file" ]; then
echo "Checking $config_file"
# Ensure the bootstrap script is sourced from the shell configuration file
source_line="if [ -f \"$bootstrap_file\" ]; then . \"$bootstrap_file\"; fi"
if ! grep -qF -- "$source_line" "$config_file"; then
echo -e "\n# Load custom aliases\n$source_line" >> "$config_file"
echo "Added source command for $bootstrap_file in $config_file."
fi
sed -i '' '/alias fabric=/d' "$config_file"
sed -i '' '/fabric --pattern/d' "$config_file"
else
echo "$config_file does not exist."
fi
done
# Add aliases to the bootstrap file
for cmd in "${commands[@]}"; do
CMD_PATH=$(poetry run which $cmd 2>/dev/null)
if [ -z "$CMD_PATH" ]; then
echo "Command $cmd not found in the current Poetry environment."
continue
fi
# Check if the alias already exists in the bootstrap file
if ! grep -qF "alias $cmd=" "$bootstrap_file"; then
echo "alias $cmd='$CMD_PATH'" >> "$bootstrap_file"
echo "Added alias for $cmd to $bootstrap_file."
fi
done
echo "Setup completed. Please restart your terminal or source your configuration files to apply changes."
Loading…
Cancel
Save