Browse Source

Merge branch 'main' into output-saver

pull/148/head
xssdoctor 8 months ago committed by GitHub
parent
commit
4d36165db4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 1
      .python-version
  2. 96
      README.md
  3. 3
      helpers/README.md
  4. 49
      helpers/yt.py
  5. 1
      installer/client/cli/agents/.python-version
  6. 81
      installer/client/cli/agents/example.py
  7. 83
      installer/client/cli/fabric.py
  8. 6
      installer/client/cli/p.py
  9. 496
      installer/client/cli/utils.py
  10. 8
      installer/client/gui/package-lock.json
  11. 2
      installer/client/gui/package.json
  12. 31
      patterns/analyze_tech_impact/system.md
  13. 0
      patterns/analyze_tech_impact/user.md
  14. 2
      patterns/create_command/README.md
  15. 2
      patterns/create_threat_model/system.md
  16. 2
      patterns/create_visualization/system.md
  17. 21
      patterns/extract_algorithm_update_recommendations/system.md
  18. 0
      patterns/extract_algorithm_update_recommendations/user.md
  19. 2
      patterns/extract_article_wisdom/README.md
  20. 24
      patterns/extract_ideas/system.md
  21. 27
      patterns/extract_main_idea/system.md
  22. 41
      patterns/extract_patterns/system.md
  23. 34
      patterns/extract_predictions/system.md
  24. 2
      patterns/extract_wisdom/README.md
  25. 26
      patterns/find_hidden_message/system.md
  26. 77
      patterns/label_and_rate/system.md
  27. 36
      patterns/provide_guidance/system.md
  28. 15
      patterns/summarize_git_changes/system.md
  29. 8
      patterns/summarize_rpg_session/system.md
  30. 0
      patterns/summarize_rpg_session/user.md
  31. 2
      patterns/write_semgrep_rule/system.md
  32. 769
      poetry.lock
  33. 9
      pyproject.toml
  34. 71
      setup.sh

1
.python-version

@ -1 +0,0 @@
3.10

96
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)
@ -47,11 +47,19 @@
<br />
## Introduction video
> [!NOTE]
> 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 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 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>
@ -143,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:
- Installs python dependencies.
- Creates aliases in your OS. It should update `~/.bashrc`, `/.zshrc`, and `~/.bash_profile` if they are present in your file system.
Use WSL and follow the Linux instructions.
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
@ -194,25 +201,52 @@ Once you have it all set up, here's how to use it.
`fabric -h`
```bash
fabric [-h] [--text TEXT] [--copy] [--output [OUTPUT]] [--stream] [--list]
[--update] [--pattern PATTERN] [--setup]
An open-source framework for augmenting humans using AI.
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. 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. 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
--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 realtime.
NOTE: You will not be able to pipe the output into another
command.
--list, -l List available patterns
--update, -u Update patterns
--pattern PATTERN, -p PATTERN
The pattern (prompt) to use
--setup Set up your fabric instance
--stream, -s Use this option if you want to see
```
#### Example commands

3
helpers/README.md

@ -56,7 +56,7 @@ options:
`save` is a "tee-like" utility to pipeline saving of content, while keeping the output stream intact. Can optionally generate "frontmatter" for PKM utilities like Obsidian via the
"FABRIC_FRONTMATTER" environment variable
### Environment Variables
If you'd like to default variables, set them in `~/.config/fabric/.env`. `FABRIC_OUTPUT_PATH` needs to be set so `save` where to write. `FABRIC_FRONTMATTER_TAGS` is optional, but useful for tracking how tags have entered your PKM, if that's important to you.
@ -89,3 +89,4 @@ tags: fabric-extraction stub-for-name extra-tag
---
test
```

49
helpers/yt.py

@ -11,17 +11,17 @@ import argparse
def get_video_id(url):
# Extract video ID from URL
pattern = r'(?:https?:\/\/)?(?:www\.)?(?:youtube\.com\/(?:[^\/\n\s]+\/\S+\/|(?:v|e(?:mbed)?)\/|\S*?[?&]v=)|youtu\.be\/)([a-zA-Z0-9_-]{11})'
pattern = r"(?:https?:\/\/)?(?:www\.)?(?:youtube\.com\/(?:[^\/\n\s]+\/\S+\/|(?:v|e(?:mbed)?)\/|\S*?[?&]v=)|youtu\.be\/)([a-zA-Z0-9_-]{11})"
match = re.search(pattern, url)
return match.group(1) if match else None
def main_function(url, options):
# Load environment variables from .env file
load_dotenv(os.path.expanduser('~/.config/fabric/.env'))
load_dotenv(os.path.expanduser("~/.config/fabric/.env"))
# Get YouTube API key from environment variable
api_key = os.getenv('YOUTUBE_API_KEY')
api_key = os.getenv("YOUTUBE_API_KEY")
if not api_key:
print("Error: YOUTUBE_API_KEY not found in ~/.config/fabric/.env")
return
@ -34,25 +34,23 @@ def main_function(url, options):
try:
# Initialize the YouTube API client
youtube = build('youtube', 'v3', developerKey=api_key)
youtube = build("youtube", "v3", developerKey=api_key)
# Get video details
video_response = youtube.videos().list(
id=video_id,
part='contentDetails'
).execute()
video_response = (
youtube.videos().list(id=video_id, part="contentDetails").execute()
)
# Extract video duration and convert to minutes
duration_iso = video_response['items'][0]['contentDetails']['duration']
duration_iso = video_response["items"][0]["contentDetails"]["duration"]
duration_seconds = isodate.parse_duration(duration_iso).total_seconds()
duration_minutes = round(duration_seconds / 60)
# Get video transcript
try:
transcript_list = YouTubeTranscriptApi.get_transcript(video_id)
transcript_text = ' '.join([item['text']
for item in transcript_list])
transcript_text = transcript_text.replace('\n', ' ')
transcript_text = " ".join([item["text"] for item in transcript_list])
transcript_text = transcript_text.replace("\n", " ")
except Exception as e:
transcript_text = f"Transcript not available. ({e})"
@ -63,31 +61,30 @@ def main_function(url, options):
print(transcript_text)
else:
# Create JSON object
output = {
"transcript": transcript_text,
"duration": duration_minutes
}
output = {"transcript": transcript_text, "duration": duration_minutes}
# Print JSON object
print(json.dumps(output))
except HttpError as e:
print(f"Error: Failed to access YouTube API. Please check your YOUTUBE_API_KEY and ensure it is valid: {e}")
def main():
parser = argparse.ArgumentParser(
description='yt (video meta) extracts metadata about a video, such as the transcript and the video\'s duration. By Daniel Miessler.')
parser.add_argument('url', nargs='?', help='YouTube video URL')
parser.add_argument('--duration', action='store_true',
help='Output only the duration')
parser.add_argument('--transcript', action='store_true',
help='Output only the transcript')
args = parser.parse_args()
if args.url:
main_function(args.url, args)
else:
parser.print_help()
if __name__ == "__main__":
main()
description="vm (video meta) extracts metadata about a video, such as the transcript and the video's duration. By Daniel Miessler."
)
parser.add_argument("url", nargs="?", help="YouTube video URL")
parser.add_argument(
"--duration", action="store_true", help="Output only the duration"
)
parser.add_argument(
"--transcript", action="store_true", help="Output only the transcript"
)

1
installer/client/cli/agents/.python-version

@ -1 +0,0 @@
3.10

81
installer/client/cli/agents/example.py

@ -1,81 +0,0 @@
from langchain_community.tools import DuckDuckGoSearchRun
import os
from crewai import Agent, Task, Crew, Process
from dotenv import load_dotenv
import os
current_directory = os.path.dirname(os.path.realpath(__file__))
config_directory = os.path.expanduser("~/.config/fabric")
env_file = os.path.join(config_directory, ".env")
load_dotenv(env_file)
os.environ['OPENAI_MODEL_NAME'] = 'gpt-4-0125-preview'
# You can choose to use a local model through Ollama for example. See https://docs.crewai.com/how-to/LLM-Connections/ for more information.
# osOPENAI_API_BASE='http://localhost:11434/v1'
# OPENAI_MODEL_NAME='openhermes' # Adjust based on available model
# OPENAI_API_KEY=''
# Install duckduckgo-search for this example:
# !pip install -U duckduckgo-search
search_tool = DuckDuckGoSearchRun()
# Define your agents with roles and goals
researcher = Agent(
role='Senior Research Analyst',
goal='Uncover cutting-edge developments in AI and data science',
backstory="""You work at a leading tech think tank.
Your expertise lies in identifying emerging trends.
You have a knack for dissecting complex data and presenting actionable insights.""",
verbose=True,
allow_delegation=False,
tools=[search_tool]
# You can pass an optional llm attribute specifying what mode you wanna use.
# It can be a local model through Ollama / LM Studio or a remote
# model like OpenAI, Mistral, Antrophic or others (https://docs.crewai.com/how-to/LLM-Connections/)
#
# import os
#
# OR
#
# from langchain_openai import ChatOpenAI
# llm=ChatOpenAI(model_name="gpt-3.5", temperature=0.7)
)
writer = Agent(
role='Tech Content Strategist',
goal='Craft compelling content on tech advancements',
backstory="""You are a renowned Content Strategist, known for your insightful and engaging articles.
You transform complex concepts into compelling narratives.""",
verbose=True,
allow_delegation=True
)
# Create tasks for your agents
task1 = Task(
description="""Conduct a comprehensive analysis of the latest advancements in AI in 2024.
Identify key trends, breakthrough technologies, and potential industry impacts.""",
expected_output="Full analysis report in bullet points",
agent=researcher
)
task2 = Task(
description="""Using the insights provided, develop an engaging blog
post that highlights the most significant AI advancements.
Your post should be informative yet accessible, catering to a tech-savvy audience.
Make it sound cool, avoid complex words so it doesn't sound like AI.""",
expected_output="Full blog post of at least 4 paragraphs",
agent=writer
)
# Instantiate your crew with a sequential process
crew = Crew(
agents=[researcher, writer],
tasks=[task1, task2],
verbose=2, # You can set it to 1 or 2 to different logging levels
)
# Get your crew to work!
result = crew.kickoff()
print("######################")
print(result)

83
installer/client/cli/fabric.py

@ -1,7 +1,6 @@
from .utils import Standalone, Update, Setup, Alias, AgentSetup
from .utils import Standalone, Update, Setup, Alias
import argparse
import sys
import time
import os
@ -16,12 +15,11 @@ def main():
parser.add_argument(
"--copy", "-C", help="Copy the response to the clipboard", action="store_true"
)
subparsers = parser.add_subparsers(dest='command', help='Sub-command help')
agents_parser = subparsers.add_parser('agents', help='Crew command help')
agents_parser.add_argument(
"trip_planner", help="The origin city for the trip")
agents_parser.add_argument(
'ApiKeys', help="enter API keys for tools", action="store_true")
parser.add_argument(
'--agents', '-a', choices=['trip_planner', 'ApiKeys'],
help="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."
)
parser.add_argument(
"--output",
"-o",
@ -39,18 +37,25 @@ def main():
parser.add_argument(
"--list", "-l", help="List available patterns", action="store_true"
)
parser.add_argument('--clear', help="Clears your persistent model choice so that you can once again use the --model flag",
action="store_true")
parser.add_argument(
"--update", "-u", help="Update patterns", action="store_true")
"--update", "-u", help="Update patterns. NOTE: This will revert the default model to gpt4-turbo. please run --changeDefaultModel to once again set default model", action="store_true")
parser.add_argument("--pattern", "-p", help="The pattern (prompt) to use")
parser.add_argument(
"--setup", help="Set up your fabric instance", action="store_true"
)
parser.add_argument('--changeDefaultModel',
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 (GPT-4 by default)", 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"
)
parser.add_argument('--remoteOllamaServer',
help='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')
parser.add_argument('--context', '-c',
help="Use Context file (context.md) to add context to your pattern", action="store_true")
@ -64,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.")
@ -73,19 +78,18 @@ def main():
Update()
Alias()
sys.exit()
if args.command == "agents":
from .agents.trip_planner.main import planner_cli
if not args.trip_planner:
print("Please provide an agent")
print(f"Available Agents:")
for agent in tripcrew.agents:
print(agent)
sys.exit
elif args.trip_planner:
if args.changeDefaultModel:
Setup().default_model(args.changeDefaultModel)
sys.exit()
if args.agents:
# Handle the agents logic
if args.agents == 'trip_planner':
from .agents.trip_planner.main import planner_cli
tripcrew = planner_cli()
tripcrew.ask()
sys.exit()
if args.ApiKeys:
elif args.agents == 'ApiKeys':
from .utils import AgentSetup
AgentSetup().run()
sys.exit()
if args.update:
@ -96,6 +100,10 @@ def main():
if not os.path.exists(os.path.join(config, "context.md")):
print("Please create a context.md file in ~/.config/fabric")
sys.exit()
if args.clear:
Setup().clean_env()
print("Model choice cleared. please restart your session to use the --model flag.")
sys.exit()
standalone = Standalone(args, args.pattern)
if args.list:
try:
@ -107,27 +115,50 @@ def main():
print("No patterns found")
sys.exit()
if args.listmodels:
standalone.fetch_available_models()
gptmodels, localmodels, claudemodels = standalone.fetch_available_models()
print("GPT Models:")
for model in gptmodels:
print(model)
print("\nLocal Models:")
for model in localmodels:
print(model)
print("\nClaude Models:")
for model in claudemodels:
print(model)
sys.exit()
if args.text is not None:
text = args.text
else:
text = standalone.get_cli_input()
if args.stream and not args.context:
standalone.streamMessage(text)
if args.remoteOllamaServer:
standalone.streamMessage(text, host=args.remoteOllamaServer)
else:
standalone.streamMessage(text)
sys.exit()
if args.stream and args.context:
with open(config_context, "r") as f:
context = f.read()
standalone.streamMessage(text, context=context)
if args.remoteOllamaServer:
standalone.streamMessage(
text, context=context, host=args.remoteOllamaServer)
else:
standalone.streamMessage(text, context=context)
sys.exit()
elif args.context:
with open(config_context, "r") as f:
context = f.read()
standalone.sendMessage(text, context=context)
if args.remoteOllamaServer:
standalone.sendMessage(
text, context=context, host=args.remoteOllamaServer)
else:
standalone.sendMessage(text, context=context)
sys.exit()
else:
standalone.sendMessage(text)
if args.remoteOllamaServer:
standalone.sendMessage(text, host=args.remoteOllamaServer)
else:
standalone.sendMessage(text)
sys.exit()

6
installer/client/cli/p.py

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

496
installer/client/cli/utils.py

@ -1,14 +1,14 @@
import requests
import os
from openai import OpenAI
import asyncio
import pyperclip
import sys
import platform
from dotenv import load_dotenv
from requests.exceptions import HTTPError
from tqdm import tqdm
import zipfile
import tempfile
import re
import shutil
current_directory = os.path.dirname(os.path.realpath(__file__))
@ -40,18 +40,73 @@ class Standalone:
apikey = os.environ["OPENAI_API_KEY"]
self.client = OpenAI()
self.client.api_key = apikey
except KeyError:
print("OPENAI_API_KEY not found in environment variables.")
except FileNotFoundError:
except:
print("No API key found. Use the --apikey option to set the key")
sys.exit()
self.local = False
self.config_pattern_directory = config_directory
self.pattern = pattern
self.args = args
self.model = args.model
self.model = None
if args.model:
self.model = args.model
else:
try:
self.model = os.environ["DEFAULT_MODEL"]
except:
self.model = 'gpt-4-turbo-preview'
self.claude = False
sorted_gpt_models, ollamaList, claudeList = self.fetch_available_models()
self.local = self.model.strip() in ollamaList
self.claude = self.model.strip() in claudeList
async def localChat(self, messages, host=''):
from ollama import AsyncClient
response = None
if host:
response = await AsyncClient(host=host).chat(model=self.model, messages=messages, host=host)
else:
response = await AsyncClient().chat(model=self.model, messages=messages)
print(response['message']['content'])
async def localStream(self, messages, host=''):
from ollama import AsyncClient
if host:
async for part in await AsyncClient(host=host).chat(model=self.model, messages=messages, stream=True, host=host):
print(part['message']['content'], end='', flush=True)
else:
async for part in await AsyncClient().chat(model=self.model, messages=messages, stream=True):
print(part['message']['content'], end='', flush=True)
async def claudeStream(self, system, user):
from anthropic import AsyncAnthropic
self.claudeApiKey = os.environ["CLAUDE_API_KEY"]
Streamingclient = AsyncAnthropic(api_key=self.claudeApiKey)
async with Streamingclient.messages.stream(
max_tokens=4096,
system=system,
messages=[user],
model=self.model, temperature=0.0, top_p=1.0
) as stream:
async for text in stream.text_stream:
print(text, end="", flush=True)
print()
message = await stream.get_final_message()
async def claudeChat(self, system, user):
from anthropic import Anthropic
self.claudeApiKey = os.environ["CLAUDE_API_KEY"]
client = Anthropic(api_key=self.claudeApiKey)
message = client.messages.create(
max_tokens=4096,
system=system,
messages=[user],
model=self.model,
temperature=0.0, top_p=1.0
)
print(message.content[0].text)
def streamMessage(self, input_data: str, context=""):
def streamMessage(self, input_data: str, context="", host=''):
""" Stream a message and handle exceptions.
Args:
@ -69,6 +124,7 @@ class Standalone:
)
user_message = {"role": "user", "content": f"{input_data}"}
wisdom_File = os.path.join(current_directory, wisdomFilePath)
system = ""
buffer = ""
if self.pattern:
try:
@ -89,36 +145,55 @@ class Standalone:
else:
messages = [user_message]
try:
stream = self.client.chat.completions.create(
model=self.model,
messages=messages,
temperature=0.0,
top_p=1,
frequency_penalty=0.1,
presence_penalty=0.1,
stream=True,
)
for chunk in stream:
if chunk.choices[0].delta.content is not None:
char = chunk.choices[0].delta.content
buffer += char
if char not in ["\n", " "]:
print(char, end="")
elif char == " ":
print(" ", end="") # Explicitly handle spaces
elif char == "\n":
print() # Handle newlines
sys.stdout.flush()
if self.local:
if host:
asyncio.run(self.localStream(messages, host=host))
else:
asyncio.run(self.localStream(messages))
elif self.claude:
from anthropic import AsyncAnthropic
asyncio.run(self.claudeStream(system, user_message))
else:
stream = self.client.chat.completions.create(
model=self.model,
messages=messages,
temperature=0.0,
top_p=1,
frequency_penalty=0.1,
presence_penalty=0.1,
stream=True,
)
for chunk in stream:
if chunk.choices[0].delta.content is not None:
char = chunk.choices[0].delta.content
buffer += char
if char not in ["\n", " "]:
print(char, end="")
elif char == " ":
print(" ", end="") # Explicitly handle spaces
elif char == "\n":
print() # Handle newlines
sys.stdout.flush()
except Exception as e:
print(f"Error: {e}")
print(e)
if "All connection attempts failed" in str(e):
print(
"Error: cannot connect to llama2. If you have not already, please visit https://ollama.com for installation instructions")
if "CLAUDE_API_KEY" in str(e):
print(
"Error: CLAUDE_API_KEY not found in environment variables. Please run --setup and add the key")
if "overloaded_error" in str(e):
print(
"Error: Fabric is working fine, but claude is overloaded. Please try again later.")
else:
print(f"Error: {e}")
print(e)
if self.args.copy:
pyperclip.copy(buffer)
if self.args.output:
with open(self.args.output, "w") as f:
f.write(buffer)
def sendMessage(self, input_data: str, context=""):
def sendMessage(self, input_data: str, context="", host=''):
""" Send a message using the input data and generate a response.
Args:
@ -136,6 +211,7 @@ class Standalone:
)
user_message = {"role": "user", "content": f"{input_data}"}
wisdom_File = os.path.join(current_directory, wisdomFilePath)
system = ""
if self.pattern:
try:
with open(wisdom_File, "r") as f:
@ -155,44 +231,81 @@ class Standalone:
else:
messages = [user_message]
try:
response = self.client.chat.completions.create(
model=self.model,
messages=messages,
temperature=0.0,
top_p=1,
frequency_penalty=0.1,
presence_penalty=0.1,
)
print(response.choices[0].message.content)
if self.local:
if host:
asyncio.run(self.localChat(messages, host=host))
else:
asyncio.run(self.localChat(messages))
elif self.claude:
asyncio.run(self.claudeChat(system, user_message))
else:
response = self.client.chat.completions.create(
model=self.model,
messages=messages,
temperature=0.0,
top_p=1,
frequency_penalty=0.1,
presence_penalty=0.1,
)
print(response.choices[0].message.content)
if self.args.copy:
pyperclip.copy(response.choices[0].message.content)
if self.args.output:
with open(self.args.output, "w") as f:
f.write(response.choices[0].message.content)
except Exception as e:
print(f"Error: {e}")
print(e)
if self.args.copy:
pyperclip.copy(response.choices[0].message.content)
if self.args.output:
with open(self.args.output, "w") as f:
f.write(response.choices[0].message.content)
if "All connection attempts failed" in str(e):
print(
"Error: cannot connect to llama2. If you have not already, please visit https://ollama.com for installation instructions")
if "CLAUDE_API_KEY" in str(e):
print(
"Error: CLAUDE_API_KEY not found in environment variables. Please run --setup and add the key")
if "overloaded_error" in str(e):
print(
"Error: Fabric is working fine, but claude is overloaded. Please try again later.")
if "Attempted to call a sync iterator on an async stream" in str(e):
print("Error: There is a problem connecting fabric with your local ollama installation. Please visit https://ollama.com for installation instructions. It is possible that you have chosen the wrong model. Please run fabric --listmodels to see the available models and choose the right one with fabric --model <model> or fabric --changeDefaultModel. If this does not work. Restart your computer (always a good idea) and try again. If you are still having problems, please visit https://ollama.com for installation instructions.")
else:
print(f"Error: {e}")
print(e)
def fetch_available_models(self):
headers = {
"Authorization": f"Bearer {self.client.api_key}"
}
response = requests.get(
"https://api.openai.com/v1/models", headers=headers)
if response.status_code == 200:
models = response.json().get("data", [])
# Filter only gpt models
gpt_models = [model for model in models if model.get(
"id", "").startswith(("gpt"))]
# Sort the models alphabetically by their ID
sorted_gpt_models = sorted(gpt_models, key=lambda x: x.get("id"))
for model in sorted_gpt_models:
print(model.get("id"))
else:
print(f"Failed to fetch models: HTTP {response.status_code}")
gptlist = []
fullOllamaList = []
claudeList = ['claude-3-opus-20240229',
'claude-3-sonnet-20240229', 'claude-2.1']
try:
headers = {
"Authorization": f"Bearer {self.client.api_key}"
}
response = requests.get(
"https://api.openai.com/v1/models", headers=headers)
if response.status_code == 200:
models = response.json().get("data", [])
# Filter only gpt models
gpt_models = [model for model in models if model.get(
"id", "").startswith(("gpt"))]
# Sort the models alphabetically by their ID
sorted_gpt_models = sorted(
gpt_models, key=lambda x: x.get("id"))
for model in sorted_gpt_models:
gptlist.append(model.get("id"))
else:
print(f"Failed to fetch models: HTTP {response.status_code}")
sys.exit()
except:
print('No OpenAI API key found. Please run fabric --setup and add the key if you wish to interact with openai')
import ollama
try:
default_modelollamaList = ollama.list()['models']
for model in default_modelollamaList:
fullOllamaList.append(model['name'])
except:
fullOllamaList = []
return gptlist, fullOllamaList, claudeList
def get_cli_input(self):
""" aided by ChatGPT; uses platform library
@ -263,57 +376,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, ".bashrc")):
self.config_files.append(os.path.join(home_directory, ".bashrc"))
if os.path.exists(os.path.join(home_directory, ".zshrc")):
self.config_files.append(os.path.join(home_directory, ".zshrc"))
if os.path.exists(os.path.join(home_directory, ".bash_profile")):
self.config_files.append(os.path.join(
home_directory, ".bash_profile"))
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 find_line(self, name):
for file in self.config_files:
with open(file, "r") as f:
lines = f.readlines()
for line in lines:
if line.strip("\n") == f"alias ${name}='{alias}'":
return line
self.home_directory = os.path.expanduser("~")
patternsFolder = os.path.join(
self.home_directory, ".config/fabric/patterns")
self.patterns = os.listdir(patternsFolder)
def add_patterns(self):
allPatterns = os.listdir(self.patterns)
for pattern in allPatterns:
self.add(pattern, f"fabric --pattern {pattern}")
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:
@ -328,7 +399,74 @@ 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 = []
self.claudeList = ['claude-3-opus-20240229']
load_dotenv(self.env_file)
try:
openaiapikey = os.environ["OPENAI_API_KEY"]
self.openaiapi_key = openaiapikey
except:
pass
try:
self.fetch_available_models()
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}"
}
response = requests.get(
"https://api.openai.com/v1/models", headers=headers)
if response.status_code == 200:
models = response.json().get("data", [])
# Filter only gpt models
gpt_models = [model for model in models if model.get(
"id", "").startswith(("gpt"))]
# Sort the models alphabetically by their ID
sorted_gpt_models = sorted(
gpt_models, key=lambda x: x.get("id"))
for model in sorted_gpt_models:
self.gptlist.append(model.get("id"))
else:
print(f"Failed to fetch models: HTTP {response.status_code}")
sys.exit()
import ollama
try:
default_modelollamaList = ollama.list()['models']
for model in default_modelollamaList:
self.fullOllamaList.append(model['name'])
except:
self.fullOllamaList = []
allmodels = self.gptlist + self.fullOllamaList + self.claudeList
return allmodels
def api_key(self, api_key):
""" Set the OpenAI API key in the environment file.
@ -342,11 +480,111 @@ class Setup:
Raises:
OSError: If the environment file does not exist or cannot be accessed.
"""
if not os.path.exists(self.env_file):
api_key = api_key.strip()
if not os.path.exists(self.env_file) and api_key:
with open(self.env_file, "w") as f:
f.write(f"OPENAI_API_KEY={api_key}")
f.write(f"OPENAI_API_KEY={api_key}\n")
print(f"OpenAI API key set to {api_key}")
elif api_key:
# erase the line OPENAI_API_KEY=key and write the new key
with open(self.env_file, "r") as f:
lines = f.readlines()
with open(self.env_file, "w") as f:
for line in lines:
if "OPENAI_API_KEY" not in line:
f.write(line)
f.write(f"OPENAI_API_KEY={api_key}\n")
def claude_key(self, claude_key):
""" Set the Claude API key in the environment file.
Args:
claude_key (str): The API key to be set.
Returns:
None
Raises:
OSError: If the environment file does not exist or cannot be accessed.
"""
claude_key = claude_key.strip()
if os.path.exists(self.env_file) and claude_key:
with open(self.env_file, "r") as f:
lines = f.readlines()
with open(self.env_file, "w") as f:
for line in lines:
if "CLAUDE_API_KEY" not in line:
f.write(line)
f.write(f"CLAUDE_API_KEY={claude_key}\n")
elif claude_key:
with open(self.env_file, "w") as f:
f.write(f"CLAUDE_API_KEY={claude_key}\n")
def youtube_key(self, youtube_key):
""" Set the YouTube API key in the environment file.
Args:
youtube_key (str): The API key to be set.
Returns:
None
Raises:
OSError: If the environment file does not exist or cannot be accessed.
"""
youtube_key = youtube_key.strip()
if os.path.exists(self.env_file) and youtube_key:
with open(self.env_file, "r") as f:
lines = f.readlines()
with open(self.env_file, "w") as f:
for line in lines:
if "YOUTUBE_API_KEY" not in line:
f.write(line)
f.write(f"YOUTUBE_API_KEY={youtube_key}\n")
elif youtube_key:
with open(self.env_file, "w") as f:
f.write(f"YOUTUBE_API_KEY={youtube_key}\n")
def default_model(self, model):
"""Set the default model in the environment file.
Args:
model (str): The model to be set.
"""
model = model.strip()
if model:
# Write or update the DEFAULT_MODEL in env_file
allModels = self.claudeList + self.fullOllamaList + self.gptlist
if model not in allModels:
print(
f"Error: {model} is not a valid model. Please run fabric --listmodels to see the available models.")
sys.exit()
# Compile regular expressions outside of the loop for efficiency
# Check for shell configuration files
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()
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 patterns(self):
""" Method to update patterns and exit the system.
@ -367,9 +605,17 @@ class Setup:
"""
print("Welcome to Fabric. Let's get started.")
apikey = input("Please enter your OpenAI API key\n")
self.api_key(apikey.strip())
apikey = input(
"Please enter your OpenAI API key. If you do not have one or if you have already entered it, press enter.\n")
self.api_key(apikey)
print("Please enter your claude API key. If you do not have one, or if you have already entered it, press enter.\n")
claudekey = input()
self.claude_key(claudekey)
print("Please enter your YouTube API key. If you do not have one, or if you have already entered it, press enter.\n")
youtubekey = input()
self.youtube_key(youtubekey)
self.patterns()
self.update_shconfigs()
class Transcribe:
@ -379,7 +625,7 @@ class Transcribe:
of a YouTube video designated with the video_id
Input:
the video id specifing a YouTube video
the video id specifying a YouTube video
an example url for a video: https://www.youtube.com/watch?v=vF-MQmVxnCs&t=306s
the video id is vF-MQmVxnCs&t=306s
@ -411,8 +657,8 @@ class AgentSetup:
"""
print("Welcome to Fabric. Let's get started.")
browserless = input("Please enter your Browserless API key\n")
serper = input("Please enter your Serper API key\n")
browserless = input("Please enter your Browserless API key\n").strip()
serper = input("Please enter your Serper API key\n").strip()
# Entries to be added
browserless_entry = f"BROWSERLESS_API_KEY={browserless}"

8
installer/client/gui/package-lock.json generated

@ -17,7 +17,7 @@
},
"devDependencies": {
"dotenv": "^16.4.1",
"electron": "^28.2.2",
"electron": "^28.2.6",
"openai": "^4.27.0"
}
},
@ -522,9 +522,9 @@
}
},
"node_modules/electron": {
"version": "28.2.2",
"resolved": "https://registry.npmjs.org/electron/-/electron-28.2.2.tgz",
"integrity": "sha512-8UcvIGFcjplHdjPFNAHVFg5bS0atDyT3Zx21WwuE4iLfxcAMsyMEOgrQX3im5LibA8srwsUZs7Cx0JAUfcQRpw==",
"version": "28.2.6",
"resolved": "https://registry.npmjs.org/electron/-/electron-28.2.6.tgz",
"integrity": "sha512-RuhbW+ifvh3DqnVlHCcCKhKIFOxTktq1GN1gkIkEZ8y5LEZfcjOkxB2s6Fd1S6MzsMZbiJti+ZJG5hXS4SDVLQ==",
"dev": true,
"hasInstallScript": true,
"dependencies": {

2
installer/client/gui/package.json

@ -10,7 +10,7 @@
"license": "ISC",
"devDependencies": {
"dotenv": "^16.4.1",
"electron": "^28.2.2",
"electron": "^28.2.6",
"openai": "^4.27.0"
},
"dependencies": {

31
patterns/analyze_tech_impact/system.md

@ -0,0 +1,31 @@
# IDENTITY and PURPOSE
You are a technology impact analysis service, focused on determining the societal impact of technology projects. Your goal is to break down the project's intentions, outcomes, and its broader implications for society, including any ethical considerations.
Take a moment to think about how to best achieve this goal using the following steps.
## OUTPUT SECTIONS
- Summarize the technology project and its primary objectives in a 25-word sentence in a section called SUMMARY.
- List the key technologies and innovations utilized in the project in a section called TECHNOLOGIES USED.
- Identify the target audience or beneficiaries of the project in a section called TARGET AUDIENCE.
- Outline the project's anticipated or achieved outcomes in a section called OUTCOMES. Use a bulleted list with each bullet not exceeding 25 words.
- Analyze the potential or observed societal impact of the project in a section called SOCIETAL IMPACT. Consider both positive and negative impacts.
- Examine any ethical considerations or controversies associated with the project in a section called ETHICAL CONSIDERATIONS. Rate the severity of ethical concerns as NONE, LOW, MEDIUM, HIGH, or CRITICAL.
- Discuss the sustainability of the technology or project from an environmental, economic, and social perspective in a section called SUSTAINABILITY.
- Based on all the analysis performed above, output a 25-word summary evaluating the overall benefit of the project to society and its sustainability. Rate the project's societal benefit and sustainability on a scale from VERY LOW, LOW, MEDIUM, HIGH, to VERY HIGH in a section called SUMMARY and RATING.
## OUTPUT INSTRUCTIONS
- You only output Markdown.
- Create the output using the formatting above.
- In the markdown, don't use formatting like bold or italics. Make the output maximally readable in plain text.
- Do not output warnings or notes—just the requested sections.

0
patterns/label_and_rate/user.md → patterns/analyze_tech_impact/user.md

2
patterns/create_command/README.md

@ -28,7 +28,7 @@ python3 sqlmap -u https://example.com?test=id --random-agent --level=5 --risk=3
**prompt**
```
tool=nmap;echo -e "use $tool to target all hosts in the host.lst file even if they don't respond to pings. scan the top 10000 ports and save the ouptut to a text file and an xml file\n\n$($tool -h 2>&1)" | fabric --pattern create_command
tool=nmap;echo -e "use $tool to target all hosts in the host.lst file even if they don't respond to pings. scan the top 10000 ports and save the output to a text file and an xml file\n\n$($tool -h 2>&1)" | fabric --pattern create_command
```
**result**

2
patterns/create_threat_model/system.md

@ -84,7 +84,7 @@ Determine the chances of that realistically happening over the next, say, 10 yea
Multiply the Impact by the Likelihood for each scenario. That’s your Risk.
Add up all your Risk scores. That’s your Total Risk.
Subtract your Total Risk from your Value. If that number is positive, you are good to go. If that number is negative, it might be too risky to use based on your risk tolerance and the value of the feature.
Note that lots of things affect this, such as you realizing you actually care about this thing a lot more than you thought. Or realizing that you can mitigate some of the risk of one of the attacks by—say—putting your Alexa only in certain rooms and not others (like the bedroom or office). Now calcluate how that affects both Impact and Likelihood for each scenario, which will affect Total Risk.
Note that lots of things affect this, such as you realizing you actually care about this thing a lot more than you thought. Or realizing that you can mitigate some of the risk of one of the attacks by—say—putting your Alexa only in certain rooms and not others (like the bedroom or office). Now calculate how that affects both Impact and Likelihood for each scenario, which will affect Total Risk.
Going the opposite direction
Above we talked about going from Feature –> Attack Scenarios –> Determining if It’s Worth It.
But there’s another version of this where you start with a control question, such as:

2
patterns/create_visualization/system.md

@ -34,7 +34,7 @@ You always output ASCII art, even if you have to simplify the input concepts to
- Do not output any code indicators like backticks or code blocks or anything.
- You only ouptut the printable portion of the ASCII art. You do not ouptut the non-printable characters.
- You only output the printable portion of the ASCII art. You do not output the non-printable characters.
- Ensure the visualization can stand alone as a diagram that fully conveys the concept(s), and that it perfectly matches a written explanation of the concepts themselves. Start over if it can't.

21
patterns/extract_algorithm_update_recommendations/system.md

@ -0,0 +1,21 @@
# IDENTITY and PURPOSE
You are an expert interpreter of the algorithms described for doing things within content. You output a list of recommended changes to the way something is done based on the input.
# Steps
Take the input given and extract the concise, practical recommendations for how to do something within the content.
# OUTPUT INSTRUCTIONS
- Output a bulleted list of up to 3 algorithm update recommendations, each of no more than 15 words.
# OUTPUT EXAMPLE
- When evaluating a collection of things that takes time to process, weigh the later ones higher because we naturally weigh them lower due to human bias.
- When performing web app assessments, be sure to check the /backup.bak path for a 200 or 400 response.
- Add "Get sun within 30 minutes of waking up to your daily routine."
# INPUT:
INPUT:

0
patterns/summarize_git_changes/user.md → patterns/extract_algorithm_update_recommendations/user.md

2
patterns/extract_article_wisdom/README.md

@ -72,7 +72,7 @@ curl -sS https://github.com/danielmiessler/fabric/blob/main/extract-wisdom/dmies
## Output
Here's an abridged ouptut example from `extractwisdom` (limited to only 10 items per section).
Here's an abridged output example from `extractwisdom` (limited to only 10 items per section).
```markdown
## SUMMARY:

24
patterns/extract_ideas/system.md

@ -0,0 +1,24 @@
# IDENTITY and PURPOSE
You extract surprising, insightful, and interesting information from text content. You are interested in insights related to the purpose and meaning of life, human flourishing, the role of technology in the future of humanity, artificial intelligence and its affect on humans, memes, learning, reading, books, continuous improvement, and similar topics.
Take a step back and think step-by-step about how to achieve the best possible results by following the steps below.
# STEPS
- Extract 20 to 50 of the most surprising, insightful, and/or interesting ideas from the input in a section called IDEAS:. If there are less than 50 then collect all of them. Make sure you extract at least 20.
# OUTPUT INSTRUCTIONS
- Only output Markdown.
- Extract at least 20 IDEAS from the content.
- Limit each idea bullet to a maximum of 15 words.
- Do not give warnings or notes; only output the requested sections.
- You use bulleted lists for output, not numbered lists.
- Do not repeat ideas, quotes, facts, or resources.
- Do not start items with the same opening words.
- Ensure you follow ALL these instructions when creating your output.
# INPUT
INPUT:

27
patterns/extract_main_idea/system.md

@ -0,0 +1,27 @@
# IDENTITY and PURPOSE
You extract the primary and/or most surprising, insightful, and interesting idea from any input.
Take a step back and think step-by-step about how to achieve the best possible results by following the steps below.
# STEPS
- Fully digest the content provided.
- Extract the most important idea from the content.
- In a section called MAIN IDEA, write a 15-word sentence that captures the main idea.
- In a section called MAIN RECOMMENDATION, write a 15-word sentence that captures what's recommended for people to do based on the idea.
# OUTPUT INSTRUCTIONS
- Only output Markdown.
- Do not give warnings or notes; only output the requested sections.
- Do not repeat ideas, quotes, facts, or resources.
- Do not start items with the same opening words.
- Ensure you follow ALL these instructions when creating your output.
# INPUT
INPUT:

41
patterns/extract_patterns/system.md

@ -0,0 +1,41 @@
# IDENTITY and PURPOSE
You take a collection of ideas or data or observations and you look for the most interesting and surprising patterns. These are like where the same idea or observation kept coming up over and over again.
Take a step back and think step-by-step about how to achieve the best possible results by following the steps below.
# STEPS
- Think deeply about all the input and the core concepts contained within.
- Extract 20 to 50 of the most surprising, insightful, and/or interesting pattern observed from the input into a section called PATTERNS.
- Weight the patterns by how often they were mentioned or showed up in the data, combined with how surprising, insightful, and/or interesting they are. But most importantly how often they showed up in the data.
- Each pattern should be captured as a bullet point of no more than 15 words.
- In a new section called META, talk through the process of how you assembled each pattern, where you got the pattern from, how many components of the input lead to each pattern, and other interesting data about the patterns.
- Give the names or sources of the different people or sources that combined to form a pattern. For example: "The same idea was mentioned by both John and Jane."
- Each META point should be captured as a bullet point of no more than 15 words.
- Add a section called ANALYSIS that gives a one sentence, 30-word summary of all the patterns and your analysis thereof.
- Add a section called ADVICE FOR BUILDERS that gives a set of 15-word bullets of advice for people in a startup space related to the input. For example if a builder was creating a company in this space, what should they do based on the PATTERNS and ANALYSIS above?
# OUTPUT INSTRUCTIONS
- Only output Markdown.
- Extract at least 20 PATTERNS from the content.
- Limit each idea bullet to a maximum of 15 words.
- Write in the style of someone giving helpful analysis finding patterns
- Do not give warnings or notes; only output the requested sections.
- You use bulleted lists for output, not numbered lists.
- Do not repeat ideas, quotes, facts, or resources.
- Do not start items with the same opening words.
- Ensure you follow ALL these instructions when creating your output.
# INPUT
INPUT:

34
patterns/extract_predictions/system.md

@ -0,0 +1,34 @@
# IDENTITY and PURPOSE
You fully digest input and extract the predictions made within.
Take a step back and think step-by-step about how to achieve the best possible results by following the steps below.
# STEPS
- Extract all predictions made within the content.
- For each prediction, extract the following:
- The specific prediction in less than 15 words.
- The date by which the prediction is supposed to occur.
- The confidence level given for the prediction.
- How we'll know if it's true or not.
# OUTPUT INSTRUCTIONS
- Only output valid Markdown with no bold or italics.
- Output the predictions as a bulleted list.
- Under the list, produce a predictions table that includes the following columns: Prediction, Confidence, Date, How to Verify.
- Limit each bullet to a maximum of 15 words.
- Do not give warnings or notes; only output the requested sections.
- Ensure you follow ALL these instructions when creating your output.
# INPUT
INPUT:

2
patterns/extract_wisdom/README.md

@ -72,7 +72,7 @@ curl -sS https://github.com/danielmiessler/fabric/blob/main/extract-wisdom/dmies
## Output
Here's an abridged ouptut example from `extractwisdom` (limited to only 10 items per section).
Here's an abridged output example from `extractwisdom` (limited to only 10 items per section).
```markdown
## SUMMARY:

26
patterns/find_hidden_message/system.md

@ -14,23 +14,27 @@ Take a step back and think step-by-step about how to evaluate the input and what
# OUTPUT
- In a section called OVERT MESSAGE, output a single 15-word sentence that captures the message that the user is OVERTLY talking about.
- In a section called OVERT MESSAGE, output a set of 10-word bullets that capture the OVERT, OBVIOUS, and BENIGN-SOUNDING main points he's trying to make on the surface. This is the message he's pretending to give.
- In a section called HIDDEN MESSAGE, output a single 15-word sentence that captures the TRUE, HIDDEN, CYNICAL, and POLITICAL message of the input. E.g.: "We need to start trusting our political leaders more because they are the best of us and know what's best.", or, "We need to stop trusting our liberal political leaders and elect a dictator that will protect traditional values."
- In a section called HIDDEN MESSAGE, output a set of 10-word bullets that capture the TRUE, HIDDEN, CYNICAL, and POLITICAL messages of the input. This is for the message he's actually giving.
- In a section called HIDDEN OPINIONS, output a bulleted list of 10-20 political or philosophical beliefs, captured in 10 words each, that the speaker(s) is trying to get the audience to subtly believe.
- In a section called SUPPORTING ARGUMENTS and QUOTES, output a bulleted list of justifications for how you arrived at the hidden message and opinions above. Use logic, argument, and direct quotes as the support content for each bullet.
- In a section called SUPPORTING ARGUMENTS and QUOTES, output a bulleted list of justifications for how you arrived at the hidden message and opinions above. Use logic, argument, and quotes as the support content for each bullet.
- In a section called DESIRED AUDIENCE ACTION, give a set of 10, 10-word bullets of politically-oriented actions the speaker(s) actually want to occur as a result of audience hearing and absorbing the HIDDEN MESSAGE. These should be tangible and real-world, e.g., voting Democrat or Republican, trusting or not trusting institutions, etc.
- In a section called DESIRED AUDIENCE OPINION CHANGE, give a set of 10, 10-word bullets of politically-oriented behavior changes the speaker(s) actually want to occur as a result of the content. These should be deeply political and tangible.
- In a section called CYNICAL ANALYSIS, write a single sentence structured like,
- In a section called DESIRED AUDIENCE ACTION CHANGE, give a set of 10, 10-word bullets of politically-oriented actions the speaker(s) actually want to occur as a result of the content. These should be tangible and real-world.
"**\_\_\_** wants you to believe he is (a set of characteristics) that wants you to (set of actions), but he's actually (a set of characteristics) that wants you to (set of actions)."
- In a section called MESSAGES, write a single sentence structured like, so-and-so wants you to believe he is saying X, but he is actually saying Y." Rewrite the analysis and formulation of your opinion above into this format.
- In a section called MORE BALANCED ANALYSIS, write a more forgiving and tempered single sentence structured like,
- In a section called PERCEPTIONS, write a single sentence structured like, so-and-so wants you to believe he is (a set of characteristics), but he's actually (a set of characteristics).
"**\_\_\_** is claiming to push \***\*\_\_\_\*\*** but he's actually pushing \***\*\_\_\_\*\*** in addition to the main message."
EXAMPLES OF DESIRED AUDIENCE ACTION CHANGE:
- In a section called FAVORABLE ANALYSIS, write a more positively interpreted single sentence structured like,
"While **\_\_\_** is definitely pushing ****\_\_\_**** in addition to his overt message, he does make valid points about ****\_\_\_\_****."
EXAMPLES OF DESIRED AUDIENCE ACTION
- Trust the government less.
@ -52,7 +56,7 @@ EXAMPLES OF DESIRED AUDIENCE ACTION CHANGE:
- Get your kids out of schools because they're government training camps.
END EXAMPLES OF DESIRED AUDIENCE CHANGE
END EXAMPLES OF DESIRED ACTIONS
# OUTPUT INSTRUCTIONS
@ -68,4 +72,4 @@ END EXAMPLES OF DESIRED AUDIENCE CHANGE
<CR> (new line)
"NOTE: This AI is tuned specifically to be cynical and politically-minded. Don't take it as perfect. Run it multiple times and/or go consume the original input to get a second opinion.
"NOTE: This AI is tuned specifically to be cynical and politically-minded. Don't believe everything it says. Run it multiple times and/or consume the original input to form your own opinion."

77
patterns/label_and_rate/system.md

@ -6,11 +6,45 @@ Take a deep breath and think step by step about how to perform the following to
STEPS:
1. You label the content with up to 20 single-word labels, such as: cybersecurity, philosophy, nihilism, poetry, writing, etc. You can use any labels you want, but they must be single words and you can't use the same word twice. This goes in a section called LABELS:.
1. You label the content with as many of the following labels that apply based on the content of the input. These labels go into a section called LABELS:. Do not create any new labels. Only use these.
LABEL OPTIONS TO SELECT FROM (Select All That Apply):
Meaning
Future
Business
Tutorial
Podcast
Miscellaneous
Creativity
NatSec
CyberSecurity
AI
Essay
Video
Conversation
Optimization
Personal
Writing
Human3.0
Health
Technology
Education
Leadership
Mindfulness
Innovation
Culture
Productivity
Science
Philosophy
END OF LABEL OPTIONS
2. You then rate the content based on the number of ideas in the input (below ten is bad, between 11 and 20 is good, and above 25 is excellent) combined with how well it directly and specifically matches the THEMES of: human meaning, the future of human meaning, human flourishing, the future of AI, AI's impact on humanity, human meaning in a post-AI world, continuous human improvement, enhancing human creative output, and the role of art and reading in enhancing human flourishing.
3. Rank content significantly lower if it's interesting and/or high quality but not directly related to the human aspects of the topics in step 2, e.g., math or science that doesn't discuss human creativity or meaning. Content must be highly focused human flourishing and/or human meaning to get a high score.
3. Rank content significantly lower if it's interesting and/or high quality but not directly related to the human aspects of the topics, e.g., math or science that doesn't discuss human creativity or meaning. Content must be highly focused human flourishing and/or human meaning to get a high score.
4. Also rate the content significantly lower if it's significantly political, meaning not that it mentions politics but if it's overtly or secretly advocating for populist or extreme political views.
You use the following rating levels:
@ -20,11 +54,11 @@ B Tier (Consume Original When Time Allows): 12+ ideas and/or DECENT theme matchi
C Tier (Maybe Skip It): 10+ ideas and/or SOME theme matching with the THEMES in STEP #2.
D Tier (Definitely Skip It): Few quality ideas and/or little theme matching with the THEMES in STEP #2.
4. Also provide a score between 1 and 100 for the overall quality ranking, where a 1 has low quality ideas or ideas that don't match the topics in step 2, and a 100 has very high quality ideas that closely match the themes in step 2.
5. Also provide a score between 1 and 100 for the overall quality ranking, where a 1 has low quality ideas or ideas that don't match the topics in step 2, and a 100 has very high quality ideas that closely match the themes in step 2.
5. Score content significantly lower if it's interesting and/or high quality but not directly related to the human aspects of the topics in step 2, e.g., math or science that doesn't discuss human creativity or meaning. Content must be highly focused on human flourishing and/or human meaning to get a high score.
6. Score content significantly lower if it's interesting and/or high quality but not directly related to the human aspects of the topics in THEMES, e.g., math or science that doesn't discuss human creativity or meaning. Content must be highly focused on human flourishing and/or human meaning to get a high score.
6. Score content VERY LOW if it doesn't include interesting ideas or any relation to the topics in step 2.
7. Score content VERY LOW if it doesn't include interesting ideas or any relation to the topics in THEMES.
OUTPUT:
@ -36,7 +70,7 @@ A one-sentence summary of the content and why it's compelling, in less than 30 w
LABELS:
Cybersecurity, Writing, Running, Copywriting
CyberSecurity, Writing, Health, Personal
RATING:
@ -52,28 +86,23 @@ Explanation: $$Explanation in 5 short bullets for why you gave that score.$$
OUTPUT FORMAT:
Output in JSON using the following formatting and structure:
- Use camelCase for all object keys.
- Ensure proper indentation for readability.
- Each nested level should be indented with four spaces or one tab.
- Wrap strings in double quotes.
- Separate key-value pairs with a colon followed by a space.
- End each key-value pair with a comma, except for the last pair in the object.
- Enclose the entire JSON object in curly braces.
- Check the final format for any syntax errors or missing punctuation.
Your output is ONLY in JSON. The structure looks like this:
{
"oneSentenceSummary": "The one-sentence summary.",
"labels": "label1, label2, label3",
"rating": "S Tier: (Must Consume Original Content This Week) (or whatever the rating is)",
"ratingExplanation": "The explanation given for the rating.",
"qualityScore": "the numeric quality score",
"qualityScoreExplanation": "The explanation for the quality rating."
"one-sentence-summary": "The one-sentence summary.",
"labels": "The labels that apply from the set of options above.",
"rating:": "S Tier: (Must Consume Original Content This Week) (or whatever the rating is)",
"rating-explanation:": "The explanation given for the rating.",
"quality-score": "The numeric quality score",
"quality-score-explanation": "The explanation for the quality score.",
}
ONLY OUTPUT THE JSON OBJECT ABOVE.
OUTPUT INSTRUCTIONS
- ONLY generate and use labels from the list above.
- ONLY OUTPUT THE JSON OBJECT ABOVE.
Do not output the json``` container. Just the JSON object itself.
- Do not output the json``` container. Just the JSON object itself.
INPUT:

36
patterns/provide_guidance/system.md

@ -0,0 +1,36 @@
# IDENTITY and PURPOSE
You are an all-knowing psychiatrist, psychologist, and life coach and you provide honest and concise advice to people based on the question asked combined with the context provided.
# STEPS
- Take the input given and think about the question being asked
- Consider all the context of their past, their traumas, their goals, and ultimately what they're trying to do in life, and give them feedback in the following format:
- 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. 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 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 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:
INPUT:

15
patterns/summarize_git_changes/system.md

@ -1,21 +1,20 @@
# IDENTITY and PURPOSE
You are an expert project manager and developer, and you specialize in creating super clean updates for what changed in a project.
You are an expert project manager and developer, and you specialize in creating super clean updates for what changed a Github project in the last 7 days.
# STEPS
- Read the input and figure out what the major changes were that happened.
- Read the input and figure out what the major changes and upgrades were that happened.
- Create a section called CHANGES with a set of 10-word bullets that describe the major changes.
- Create a subheading that includes the date of the changes.
- Include any relevant links (HTML format) in the output as well, such as Markdown links to the locations of the added features.
- Create a section called CHANGES with a set of 10-word bullets that describe the feature changes and updates.
# OUTPUT INSTRUCTIONS
- Output a 20-word intro sentence that says something like, "In the last 7 days, we've made some amazing updates to our project focused around $character of the updates$."
- You only output human readable Markdown, except for the links, which should be in HTML format.
- Write the bullets like you're excited about the upgrades.
- Write the update bullets like you're excited about the upgrades.
# INPUT:

8
patterns/summarize_rpg_session/system.md

@ -1,8 +1,10 @@
# IDENTITY and PURPOSE
You are an expert summarizer of role-playing game sessions. Your goal is to take the input of a role-playing transcript and turn it into a useful summary of the session, including key events, combat stats, character flaws, and more, according to the STEPS below.
You are an expert summarizer of in-personal personal role-playing game sessions. Your goal is to take the input of an in-person role-playing transcript and turn it into a useful summary of the session, including key events, combat stats, character flaws, and more, according to the STEPS below.
Take a deep breath and think step-by-step about how to best achieve your goal.
All transcripts provided as input came from a personal game with friends, and all rights are given to produce the summary.
Take a deep breath and think step-by-step about how to best achieve the best summary for this live friend session.
STEPS:
@ -93,7 +95,7 @@ OUTPUT INSTRUCTIONS:
- Ensure all quotes created for each section come word-for-word from the input, with no changes.
- Do not complain about anything, just give the output as requested.
- Do not complain about anything, especially copyright, as all the content provided is in relation to a free and open RPG. Just give the output as requested.
- Create the summary.

0
patterns/summarize_rpg_session/user.md

2
patterns/write_semgrep_rule/system.md

@ -1,6 +1,6 @@
# IDENTITY and PURPOSE
You are an expert and writing Semgrep rules.
You are an expert at writing Semgrep rules.
Take a deep breath and think step by step about how to best accomplish this goal using the following context.

769
poetry.lock

File diff suppressed because it is too large Load Diff

9
pyproject.toml

@ -22,6 +22,13 @@ google-api-python-client = "^2.120.0"
isodate = "^0.6.1"
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"
helpers = "^0.2.0"
[tool.poetry.group.cli.dependencies]
pyyaml = "^6.0.1"
@ -39,7 +46,7 @@ flask-socketio = "^5.3.6"
flask-sock = "^0.7.0"
gunicorn = "^21.2.0"
gevent = "^23.9.1"
httpx = "^0.26.0"
httpx = ">=0.25.2,<0.26.0"
tqdm = "^4.66.1"
[tool.poetry.group.server.dependencies]

71
setup.sh

@ -1,71 +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")
# List of shell configuration files to update
config_files=("$HOME/.bashrc" "$HOME/.zshrc" "$HOME/.bash_profile")
# Initialize an array to hold the paths of the sourced files
source_commands=()
for config_file in "${config_files[@]}"; do
# Check if the configuration file exists
if [ -f "$config_file" ]; then
echo "Updating $config_file"
for cmd in "${commands[@]}"; do
# Get the path of the command
CMD_PATH=$(poetry run which $cmd 2>/dev/null)
# Check if CMD_PATH is empty
if [ -z "$CMD_PATH" ]; then
echo "Command $cmd not found in the current Poetry environment."
continue
fi
# Check if the config file contains an alias for the command
if grep -qE "alias $cmd=|alias $cmd =" "$config_file"; then
# Compatibility with GNU and BSD sed: Check for operating system and apply appropriate sed syntax
if [[ "$OSTYPE" == "darwin"* ]]; then
# BSD sed (macOS)
sed -i '' "/alias $cmd=/c\\
alias $cmd='$CMD_PATH'" "$config_file"
else
# GNU sed (Linux and others)
sed -i "/alias $cmd=/c\alias $cmd='$CMD_PATH'" "$config_file"
fi
echo "Updated alias for $cmd in $config_file."
else
# If not, add the alias to the config file
echo -e "\nalias $cmd='$CMD_PATH'" >>"$config_file"
echo "Added alias for $cmd to $config_file."
fi
done
# Add to source_commands array
source_commands+=("$config_file")
else
echo "$config_file does not exist."
fi
done
# Provide instruction to source the updated files
if [ ${#source_commands[@]} -ne 0 ]; then
echo "To apply the changes, please run the following command(s) in your terminal:"
for file in "${source_commands[@]}"; do
echo "source $file"
done
else
echo "No configuration files were updated. No need to source."
fi
Loading…
Cancel
Save