Compare commits

...

28 Commits

Author SHA1 Message Date
jad2121
fbfea93b6c deleted lots of random mp3 files 2024-02-21 20:22:07 -05:00
jad2121
c4332c9ee0 added audio to text under --transcribe 2024-02-21 20:00:20 -05:00
Daniel Miessler
92f8e08aac Cleanup. 2024-02-21 09:38:07 -08:00
Daniel Miessler
62f3608144 Updated output instructions. 2024-02-21 09:14:17 -08:00
Daniel Miessler
20c1ad90bb Created a STATISTICS version of analyze_threat_report. 2024-02-21 09:11:20 -08:00
Daniel Miessler
e866eeafa6 Created a STATISTICS version of analyze_threat_report. 2024-02-21 09:09:12 -08:00
Daniel Miessler
5e48c0ef2c Created a TRENDS version of analyze_threat_report. 2024-02-21 09:06:02 -08:00
Daniel Miessler
61421c28cb Improved summary to analyze_threat_report. 2024-02-21 09:03:44 -08:00
Daniel Miessler
7ebf5bc905 Added summary to analyze_threat_report. 2024-02-21 09:01:49 -08:00
Daniel Miessler
9cd15d725c Added a threat report analysis pattern. 2024-02-21 08:59:45 -08:00
Jonathan Dunn
138c779f5e changed readme 2024-02-21 08:39:31 -05:00
jad2121
31ab369e2f changed another message 2024-02-21 06:25:21 -05:00
jad2121
983084e4f0 added a statement 2024-02-21 06:24:01 -05:00
jad2121
ed847fd332 Added aliases for individual patterns. Also fixed pattern download process 2024-02-21 06:19:54 -05:00
Daniel Miessler
373d362d35 Merge pull request #118 from mikeprivette/main
Enhanced Setup Script Compatibility and Reliability Improvements
2024-02-20 09:22:28 -08:00
Mike Privette
6dff639969 Updates
- README.md - added instructions to make sure the setup.sh script was executable as this was not explicitly stated

- setup.sh - updated sed to use `sed -i` to be compatible with Linux, MacOSX and other OS versions and added a check in the local directory taht setup.sh executes in for a pyproject.toml file because the script was looking for the .toml file in the user's home directory and throwing an error
2024-02-20 10:41:34 +00:00
Daniel Miessler
6414c26636 Updated write_essay to be more conversational and less grandiose and pompous. 2024-02-19 17:34:22 -08:00
Daniel Miessler
bc4456b310 Merge pull request #114 from fureigh/remove-ds-store
Removes stray .DS_Store file
2024-02-18 18:47:34 -08:00
Daniel Miessler
873bca5230 Merge pull request #115 from fureigh/gerunds-ahoy
Makes a minor README edit for the sake of consistency
2024-02-18 18:47:05 -08:00
Fureigh
5d984f3687 Minor README edit for verb form consistency
Change `Create` to `Creating`.
2024-02-18 17:40:08 -08:00
Fureigh
9863573ff6 Remove stray .DS_Store file 2024-02-18 17:05:08 -08:00
jad2121
335fea353b now context.md is in .config 2024-02-18 16:48:47 -05:00
jad2121
a0d264bead updated readme 2024-02-18 16:36:17 -05:00
jad2121
d15e022abf fixed context 2024-02-18 16:34:47 -05:00
jad2121
8f4ab672c6 added context to cli. edit context.md and add -C to add context to your queries 2024-02-18 13:25:07 -05:00
Daniel Miessler
b127fbec15 Updated analyze_paper with more detail and legibility. 2024-02-17 19:38:12 -08:00
Daniel Miessler
0deab1ebb3 Updated analyze_paper with more detail and legibility. 2024-02-17 19:35:09 -08:00
Daniel Miessler
8aacaee643 Added a specific version of extract_wisdom just for articles. 2024-02-17 19:03:45 -08:00
20 changed files with 631 additions and 184 deletions

View File

@@ -96,7 +96,7 @@ Fabric has Patterns for all sorts of life and work activities, including:
- Getting summaries of long, boring content
- Explaining code to you
- Turning bad documentation into usable documentation
- Create social media posts from any content input
- Creating social media posts from any content input
- And a million more…
### Our approach to prompting
@@ -146,7 +146,13 @@ git clone https://github.com/danielmiessler/fabric.git
cd fabric
```
4. Install poetry
4. Ensure the `setup.sh` script is executable. If you're not sure, you can make it executable by running the following command:
```bash
chmod +x setup.sh
```
5. Install poetry
ref.: https://python-poetry.org/docs/#installing-with-the-official-installer
@@ -154,17 +160,18 @@ ref.: https://python-poetry.org/docs/#installing-with-the-official-installer
curl -sSL https://install.python-poetry.org | python3 -
```
5. Run the `setup.sh`, which will do the following:
- Installs python dependencies.
- Creates aliases in your OS. It should update `~/.bashrc`, `/.zshrc`, and `~/.bash_profile` if they are present in your file system.
6. Run the `setup.sh`, which will do the following:
- Installs python dependencies.
- Creates aliases in your OS. It should update `~/.bashrc`, `/.zshrc`, and `~/.bash_profile` if they are present in your file system.
```bash
./setup.sh
```
6. Restart your shell to reload everything.
7. Restart your shell to reload everything.
7. Set your `OPENAI_API_KEY`.
8. Set your `OPENAI_API_KEY`.
```bash
fabric --setup
@@ -172,7 +179,7 @@ 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.
8. Now you are up and running! You can test by pulling the help.
9. Now you are up and running! You can test by pulling the help.
```bash
# Making sure the paths are set up correctly
@@ -182,7 +189,6 @@ fabric --help
> [!NOTE]
> If you're using the `server` functions, `fabric-api` and `fabric-webui` need to be run in distinct terminal windows.
### Using the `fabric` client
Once you have it all set up, here's how to use it.
@@ -228,6 +234,12 @@ pbpaste | fabric --pattern summarize
pbpaste | fabric --stream --pattern analyze_claims
```
3. **new** All of the patterns have been added as aliases to your bash (or zsh) config file
```bash
pbpaste | analyze_claims --stream
```
> [!NOTE]
> More examples coming in the next few days, including a demo video!

View File

@@ -32,7 +32,8 @@ Options include:
--pattern, -p: Select the module for analysis.
--stream, -s: Stream output to another application.
--output, -o: Save the response to a file.
--copy, -c: Copy the response to the clipboard.
--copy, -C: Copy the response to the clipboard.
--context, -c: Use Context file (context.md) to add context to your pattern
Example:

View File

@@ -0,0 +1,3 @@
# Context
please give all responses in spanish

View File

@@ -1,18 +1,20 @@
from .utils import Standalone, Update, Setup
from .utils import Standalone, Update, Setup, Alias, Whisper
import argparse
import sys
import time
import os
script_directory = os.path.dirname(os.path.realpath(__file__))
def main():
parser = argparse.ArgumentParser(
description="An open source framework for augmenting humans using AI."
)
parser.add_argument("--text", "-t", help="Text to extract summary from")
parser.add_argument(
"--copy", "-c", help="Copy the response to the clipboard", action="store_true"
"--copy", "-C", help="Copy the response to the clipboard", action="store_true"
)
parser.add_argument(
"--output",
@@ -28,10 +30,13 @@ def main():
help="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.",
action="store_true",
)
parser.add_argument('--transcribe', '-T',
help="transcribe audio, please enter the path to the audio file, or a url with the audio file")
parser.add_argument(
"--list", "-l", help="List available patterns", action="store_true"
)
parser.add_argument("--update", "-u", help="Update patterns", action="store_true")
parser.add_argument(
"--update", "-u", help="Update patterns", 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"
@@ -42,27 +47,36 @@ def main():
parser.add_argument(
"--listmodels", help="List all available models", action="store_true"
)
parser.add_argument('--context', '-c',
help="Use Context file (context.md) to add context to your pattern", action="store_true")
args = parser.parse_args()
home_holder = os.path.expanduser("~")
config = os.path.join(home_holder, ".config", "fabric")
config_patterns_directory = os.path.join(config, "patterns")
config_context = os.path.join(config, "context.md")
env_file = os.path.join(config, ".env")
if not os.path.exists(config):
os.makedirs(config)
if args.setup:
Setup().run()
Alias()
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.")
sys.exit()
if not os.path.exists(config_patterns_directory):
Update()
Alias()
sys.exit()
if args.update:
Update()
print("Your Patterns have been updated.")
Alias()
sys.exit()
if args.context:
if not os.path.exists(os.path.join(config, "context.md")):
print("Please create a context.md file in ~/.config/fabric")
sys.exit()
standalone = Standalone(args, args.pattern)
if args.list:
try:
@@ -76,14 +90,27 @@ def main():
if args.listmodels:
standalone.fetch_available_models()
sys.exit()
if args.transcribe:
whisper = Whisper()
whisper.process_file(args.transcribe)
sys.exit()
if args.text is not None:
text = args.text
else:
text = standalone.get_cli_input()
if args.stream:
if args.stream and not args.context:
standalone.streamMessage(text)
if args.stream and args.context:
with open(config_context, "r") as f:
context = f.read()
standalone.streamMessage(text, context=context)
elif args.context:
with open(config_context, "r") as f:
context = f.read()
standalone.sendMessage(text, context=context)
else:
standalone.sendMessage(text)
if __name__ == "__main__":
main()

View File

@@ -7,13 +7,16 @@ import platform
from dotenv import load_dotenv
from requests.exceptions import HTTPError
from tqdm import tqdm
import zipfile
import tempfile
import shutil
from pydub import AudioSegment
current_directory = os.path.dirname(os.path.realpath(__file__))
config_directory = os.path.expanduser("~/.config/fabric")
env_file = os.path.join(config_directory, ".env")
class Standalone:
def __init__(self, args, pattern="", env_file="~/.config/fabric/.env"):
""" Initialize the class with the provided arguments and environment file.
@@ -49,7 +52,7 @@ class Standalone:
self.args = args
self.model = args.model
def streamMessage(self, input_data: str):
def streamMessage(self, input_data: str, context=""):
""" Stream a message and handle exceptions.
Args:
@@ -71,14 +74,21 @@ class Standalone:
if self.pattern:
try:
with open(wisdom_File, "r") as f:
system = f.read()
if context:
system = context + '\n\n' + f.read()
else:
system = f.read()
system_message = {"role": "system", "content": system}
messages = [system_message, user_message]
except FileNotFoundError:
print("pattern not found")
return
else:
messages = [user_message]
if context:
user_message += {role: "system", content: context}
messages = [user_message]
else:
messages = [user_message]
try:
stream = self.client.chat.completions.create(
model=self.model,
@@ -109,7 +119,7 @@ class Standalone:
with open(self.args.output, "w") as f:
f.write(buffer)
def sendMessage(self, input_data: str):
def sendMessage(self, input_data: str, context=""):
""" Send a message using the input data and generate a response.
Args:
@@ -130,14 +140,21 @@ class Standalone:
if self.pattern:
try:
with open(wisdom_File, "r") as f:
system = f.read()
if context:
system = context + '\n\n' + f.read()
else:
system = f.read()
system_message = {"role": "system", "content": system}
messages = [system_message, user_message]
except FileNotFoundError:
print("pattern not found")
return
else:
messages = [user_message]
if context:
user_message += {'role': 'system', 'content': context}
messages = [user_message]
else:
messages = [user_message]
try:
response = self.client.chat.completions.create(
model=self.model,
@@ -159,28 +176,30 @@ class Standalone:
def fetch_available_models(self):
headers = {
"Authorization": f"Bearer { self.client.api_key }"
"Authorization": f"Bearer {self.client.api_key}"
}
response = requests.get("https://api.openai.com/v1/models", headers=headers)
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"))]
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}")
def get_cli_input(self):
""" aided by ChatGPT; uses platform library
accepts either piped input or console input
from either Windows or Linux
Args:
none
Returns:
@@ -191,129 +210,204 @@ class Standalone:
if not sys.stdin.isatty(): # Check if input is being piped
return sys.stdin.read().strip() # Read piped input
else:
return input("Enter Question: ") # Prompt user for input from console
# Prompt user for input from console
return input("Enter Question: ")
else:
return sys.stdin.read()
class Whisper:
def __init__(self):
env_file = os.path.expanduser("~/.config/fabric/.env")
load_dotenv(env_file)
try:
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:
print("No API key found. Use the --apikey option to set the key")
self.whole_response = []
def split_audio(self, file_path):
"""
Splits the audio file into segments of the given length.
Args:
- file_path: The path to the audio file.
- segment_length_ms: Length of each segment in milliseconds.
Returns:
- A list of audio segments.
"""
audio = AudioSegment.from_file(file_path)
segments = []
segment_length_ms = 10 * 60 * 1000 # 10 minutes in milliseconds
for start_ms in range(0, len(audio), segment_length_ms):
end_ms = start_ms + segment_length_ms
segment = audio[start_ms:end_ms]
segments.append(segment)
return segments
def process_segment(self, segment):
""" Transcribe an audio file and print the transcript.
Args:
audio_file (str): The path to the audio file to be transcribed.
Returns:
None
"""
try:
# if audio_file.startswith("http"):
# response = requests.get(audio_file)
# response.raise_for_status()
# with tempfile.NamedTemporaryFile(delete=False) as f:
# f.write(response.content)
# audio_file = f.name
audio_file = open(segment, "rb")
response = self.client.audio.transcriptions.create(
model="whisper-1",
file=audio_file
)
self.whole_response.append(response.text)
except Exception as e:
print(f"Error: {e}")
def process_file(self, audio_file):
""" Transcribe an audio file and print the transcript.
Args:
audio_file (str): The path to the audio file to be transcribed.
Returns:
None
"""
try:
# if audio_file.startswith("http"):
# response = requests.get(audio_file)
# response.raise_for_status()
# with tempfile.NamedTemporaryFile(delete=False) as f:
# f.write(response.content)
# audio_file = f.name
segments = self.split_audio(audio_file)
for i, segment in enumerate(segments):
segment_file_path = f"segment_{i}.mp3"
segment.export(segment_file_path, format="mp3")
self.process_segment(segment_file_path)
print(' '.join(self.whole_response))
except Exception as e:
print(f"Error: {e}")
class Update:
def __init__(self):
""" Initialize the object with default values and update patterns.
This method initializes the object with default values for root_api_url, config_directory, and pattern_directory.
It then creates the pattern_directory if it does not exist and calls the update_patterns method to update the patterns.
Raises:
OSError: If there is an issue creating the pattern_directory.
"""
self.root_api_url = "https://api.github.com/repos/danielmiessler/fabric/contents/patterns?ref=main"
"""Initialize the object with default values."""
self.repo_zip_url = "https://github.com/danielmiessler/fabric/archive/refs/heads/main.zip"
self.config_directory = os.path.expanduser("~/.config/fabric")
self.pattern_directory = os.path.join(self.config_directory, "patterns")
self.pattern_directory = os.path.join(
self.config_directory, "patterns")
os.makedirs(self.pattern_directory, exist_ok=True)
self.update_patterns() # Call the update process from a method.
print("Updating patterns...")
self.update_patterns() # Start the update process immediately
def update_patterns(self):
""" Update the patterns by downloading from the GitHub directory.
Raises:
HTTPError: If there is an HTTP error while downloading patterns.
"""
try:
self.progress_bar = tqdm(desc="Downloading Patterns…", unit="file")
self.get_github_directory_contents(
self.root_api_url, self.pattern_directory
)
# Close progress bar on success before printing the message.
self.progress_bar.close()
except HTTPError as e:
# Ensure progress bar is closed on HTTPError as well.
self.progress_bar.close()
if e.response.status_code == 403:
print(
"GitHub API rate limit exceeded. Please wait before trying again."
)
sys.exit()
"""Update the patterns by downloading the zip from GitHub and extracting it."""
with tempfile.TemporaryDirectory() as temp_dir:
zip_path = os.path.join(temp_dir, "repo.zip")
self.download_zip(self.repo_zip_url, zip_path)
extracted_folder_path = self.extract_zip(zip_path, temp_dir)
# The patterns folder will be inside "fabric-main" after extraction
patterns_source_path = os.path.join(
extracted_folder_path, "fabric-main", "patterns")
if os.path.exists(patterns_source_path):
# If the patterns directory already exists, remove it before copying over the new one
if os.path.exists(self.pattern_directory):
shutil.rmtree(self.pattern_directory)
shutil.copytree(patterns_source_path, self.pattern_directory)
print("Patterns updated successfully.")
else:
print(f"Failed to download patterns due to an HTTP error: {e}")
sys.exit() # Exit after handling the error.
print("Patterns folder not found in the downloaded zip.")
def download_file(self, url, local_path):
""" Download a file from the given URL and save it to the local path.
def download_zip(self, url, save_path):
"""Download the zip file from the specified URL."""
response = requests.get(url)
response.raise_for_status() # Check if the download was successful
with open(save_path, 'wb') as f:
f.write(response.content)
print("Downloaded zip file successfully.")
Args:
url (str): The URL of the file to be downloaded.
local_path (str): The local path where the file will be saved.
def extract_zip(self, zip_path, extract_to):
"""Extract the zip file to the specified directory."""
with zipfile.ZipFile(zip_path, 'r') as zip_ref:
zip_ref.extractall(extract_to)
print("Extracted zip file successfully.")
return extract_to # Return the path to the extracted contents
Raises:
HTTPError: If an HTTP error occurs during the download process.
"""
try:
response = requests.get(url)
response.raise_for_status()
with open(local_path, "wb") as f:
f.write(response.content)
self.progress_bar.update(1)
except HTTPError as e:
print(f"Failed to download file {url}. HTTP error: {e}")
sys.exit()
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 process_item(self, item, local_dir):
""" Process the given item and save it to the local directory.
def add(self, name, alias):
for file in self.config_files:
with open(file, "a") as f:
f.write(f"alias {name}='{alias}'\n")
Args:
item (dict): The item to be processed, containing information about the type, download URL, name, and URL.
local_dir (str): The local directory where the item will be saved.
def remove(self, pattern):
for file in self.config_files:
# Read the whole file first
with open(file, "r") as f:
wholeFile = f.read()
Returns:
None
# 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, "")
Raises:
OSError: If there is an issue creating the new directory using os.makedirs.
"""
# Write the modified content back to the file
with open(file, "w") as f:
f.write(wholeFile)
if item["type"] == "file":
self.download_file(
item["download_url"], os.path.join(local_dir, item["name"])
)
elif item["type"] == "dir":
new_dir = os.path.join(local_dir, item["name"])
os.makedirs(new_dir, exist_ok=True)
self.get_github_directory_contents(item["url"], new_dir)
def remove_all_patterns(self):
allPatterns = os.listdir(self.patterns)
for pattern in allPatterns:
self.remove(pattern)
def get_github_directory_contents(self, api_url, local_dir):
""" Get the contents of a directory from GitHub API and process each item.
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
Args:
api_url (str): The URL of the GitHub API endpoint for the directory.
local_dir (str): The local directory where the contents will be processed.
def add_patterns(self):
allPatterns = os.listdir(self.patterns)
for pattern in allPatterns:
self.add(pattern, f"fabric --pattern {pattern}")
Returns:
None
Raises:
HTTPError: If an HTTP error occurs while fetching the directory contents.
If the status code is 403, it prints a message about GitHub API rate limit exceeded
and closes the progress bar. For any other status code, it prints a message
about failing to fetch directory contents due to an HTTP error.
"""
try:
response = requests.get(api_url)
response.raise_for_status()
jsonList = response.json()
for item in jsonList:
self.process_item(item, local_dir)
except HTTPError as e:
if e.response.status_code == 403:
print(
"GitHub API rate limit exceeded. Please wait before trying again."
)
self.progress_bar.close() # Ensure the progress bar is cleaned up properly
else:
print(f"Failed to fetch directory contents due to an HTTP error: {e}")
class Setup:
def __init__(self):
@@ -324,7 +418,8 @@ class Setup:
"""
self.config_directory = os.path.expanduser("~/.config/fabric")
self.pattern_directory = os.path.join(self.config_directory, "patterns")
self.pattern_directory = os.path.join(
self.config_directory, "patterns")
os.makedirs(self.pattern_directory, exist_ok=True)
self.env_file = os.path.join(self.config_directory, ".env")
@@ -354,7 +449,6 @@ class Setup:
"""
Update()
sys.exit()
def run(self):
""" Execute the Fabric program.
@@ -370,25 +464,25 @@ class Setup:
self.api_key(apikey.strip())
self.patterns()
class Transcribe:
def youtube(video_id):
"""
This method gets the transciption
of a YouTube video designated with the video_id
Input:
the video id specifing 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
Output:
a transcript for the video
Raises:
an exception and prints error
"""
try:
transcript_list = YouTubeTranscriptApi.get_transcript(video_id)
@@ -399,5 +493,3 @@ class Transcribe:
except Exception as e:
print("Error:", e)
return None

BIN
patterns/.DS_Store vendored

Binary file not shown.

View File

@@ -6,58 +6,37 @@ Take a deep breath and think step by step about how to best accomplish this goal
# OUTPUT SECTIONS
- Extract a summary of the content in 50 words or less, including who is presenting and the content being discussed into a section called SUMMARY.
- Extract a summary of the paper and its conclusions in into a 25-word sentence called SUMMARY.
- Extract the list of authors in a section called AUTHORS.
- Extract the list of organizations the authors are associated, e.g., which university they're at, with in a section called AUTHOR ORGANIZATIONS.
- Extract the primary paper findings into a bulleted list of no more than 50 words per bullet into a section called FINDINGS.
- Extract the primary paper findings into a bulleted list of no more than 25 words per bullet into a section called FINDINGS.
- You extract the size and details of the study for the research in a section called STUDY DETAILS.
- Extract the overall structure and character of the study for the research in a section called STUDY DETAILS.
- Extract the study quality by evaluating the following items in a section called STUDY QUALITY:
- Extract the study quality by evaluating the following items in a section called STUDY QUALITY that has the following sub-sections:
### Sample size
- Study Design: (give a 25 word description, including the pertinent data and statistics.)
- Sample Size: (give a 25 word description, including the pertinent data and statistics.)
- Confidence Intervals (give a 25 word description, including the pertinent data and statistics.)
- P-value (give a 25 word description, including the pertinent data and statistics.)
- Effect Size (give a 25 word description, including the pertinent data and statistics.)
- Consistency of Results (give a 25 word description, including the pertinent data and statistics.)
- Data Analysis Method (give a 25 word description, including the pertinent data and statistics.)
- **Check the Sample Size**: The larger the sample size, the more confident you can be in the findings. A larger sample size reduces the margin of error and increases the study's power.
- Discuss any Conflicts of Interest in a section called CONFLICTS OF INTEREST. Rate the conflicts of interest as NONE DETECTED, LOW, MEDIUM, HIGH, or CRITICAL.
### Confidence intervals
- Extract the researcher's analysis and interpretation in a section called RESEARCHER'S INTERPRETATION, including how confident they are in the results being real and likely to be replicated on a scale of LOW, MEDIUM, or HIGH.
- **Look at the Confidence Intervals**: Confidence intervals provide a range within which the true population parameter lies with a certain degree of confidence (usually 95% or 99%). Narrower confidence intervals suggest a higher level of precision and confidence in the estimate.
### P-Value
- **Evaluate the P-value**: The P-value tells you the probability that the results occurred by chance. A lower P-value (typically less than 0.05) suggests that the findings are statistically significant and not due to random chance.
### Effect size
- **Consider the Effect Size**: Effect size tells you how much of a difference there is between groups. A larger effect size indicates a stronger relationship and more confidence in the findings.
### Study design
- **Review the Study Design**: Randomized controlled trials are usually considered the gold standard in research. If the study is observational, it may be less reliable.
### Consistency of results
- **Check for Consistency of Results**: If the results are consistent across multiple studies, it increases the confidence in the findings.
### Data analysis methods
- **Examine the Data Analysis Methods**: Check if the data analysis methods used are appropriate for the type of data and research question. Misuse of statistical methods can lead to incorrect conclusions.
### Researcher's interpretation
- **Assess the Researcher's Interpretation**: The researchers should interpret their results in the context of the study's limitations. Overstating the findings can misrepresent the confidence level.
### Summary
You output a 50 word summary of the quality of the paper and it's likelihood of being replicated in future work as one of three levels: High, Medium, or Low. You put that sentence and ratign into a section called SUMMARY.
- Based on all of the analysis performed above, output a 25 word summary of the quality of the paper and it's likelihood of being replicated in future work as one of five levels: VERY LOW, LOW, MEDIUM, HIGH, or VERY HIGH. You put that sentence and RATING into a section called SUMMARY and RATING.
# OUTPUT INSTRUCTIONS
- Create the output using the formatting above.
- You only output human readable Markdown.
- In the markdown, don't use formatting like bold or italics. Make the output maximially readable in plain text.
- Do not output warnings or notes—just the requested sections.
# INPUT:

View File

@@ -0,0 +1,38 @@
# IDENTITY and PURPOSE
You are a super-intelligent cybersecurity expert. You specialize in extracting the surprising, insightful, and interesting information from cybersecurity threat reports.
Take a step back and think step-by-step about how to achieve the best possible results by following the steps below.
# STEPS
- Read the entire threat report from an expert perspective, thinking deeply about what's new, interesting, and surprising in the report.
- Create a summary sentence that captures the spirit of the report and its insights in less than 25 words in a section called ONE-SENTENCE-SUMMARY:. Use plain and conversational language when creating this summary. Don't use jargon or marketing language.
- Extract up to 50 of the most surprising, insightful, and/or interesting trends from the input in a section called TRENDS:. If there are less than 50 then collect all of them. Make sure you extract at least 20.
- Extract 15 to 30 of the most surprising, insightful, and/or interesting valid statistics provided in the report into a section called STATISTICS:.
- Extract 15 to 30 of the most surprising, insightful, and/or interesting quotes from the input into a section called QUOTES:. Use the exact quote text from the input.
- Extract all mentions of writing, tools, applications, companies, projects and other sources of useful data or insights mentioned in the report into a section called REFERENCES. This should include any and all references to something that the report mentioned.
- Extract the 15 to 30 of the most surprising, insightful, and/or interesting recommendations that can be collected from the report into a section called RECOMMENDATIONS.
# OUTPUT INSTRUCTIONS
- Only output Markdown.
- Do not output the markdown code syntax, only the content.
- Do not use bold or italics formatting in the markdown output.
- Extract at least 20 TRENDS from the content.
- Extract at least 10 items for the other output sections.
- 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:

View File

@@ -0,0 +1 @@
CONTENT:

View File

@@ -0,0 +1,27 @@
# IDENTITY and PURPOSE
You are a super-intelligent cybersecurity expert. You specialize in extracting the surprising, insightful, and interesting information from cybersecurity threat reports.
Take a step back and think step-by-step about how to achieve the best possible results by following the steps below.
# STEPS
- Read the entire threat report from an expert perspective, thinking deeply about what's new, interesting, and surprising in the report.
- Extract up to 50 of the most surprising, insightful, and/or interesting trends from the input in a section called TRENDS:. If there are less than 50 then collect all of them. Make sure you extract at least 20.
# OUTPUT INSTRUCTIONS
- Only output Markdown.
- Do not output the markdown code syntax, only the content.
- Do not use bold or italics formatting in the markdown output.
- Extract at least 20 TRENDS from the content.
- 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:

View File

@@ -0,0 +1 @@
CONTENT:

View File

@@ -0,0 +1,154 @@
<div align="center">
<img src="https://beehiiv-images-production.s3.amazonaws.com/uploads/asset/file/2012aa7c-a939-4262-9647-7ab614e02601/extwis-logo-miessler.png?t=1704502975" alt="extwislogo" width="400" height="400"/>
# `/extractwisdom`
<h4><code>extractwisdom</code> is a <a href="https://github.com/danielmiessler/fabric" target="_blank">Fabric</a> pattern that <em>extracts wisdom</em> from any text.</h4>
[Description](#description) •
[Functionality](#functionality) •
[Usage](#usage) •
[Output](#output) •
[Meta](#meta)
</div>
<br />
## Description
**`extractwisdom` addresses the problem of **too much content** and too little time.**
_Not only that, but it's also too easy to forget the stuff read, watch, or listen to._
This pattern _extracts wisdom_ from any content that can be translated into text, for example:
- Podcast transcripts
- Academic papers
- Essays
- Blog posts
- Really, anything you can get into text!
## Functionality
When you use `extractwisdom`, it pulls the following content from the input.
- `IDEAS`
- Extracts the best ideas from the content, i.e., what you might have taken notes on if you were doing so manually.
- `QUOTES`
- Some of the best quotes from the content.
- `REFERENCES`
- External writing, art, and other content referenced positively during the content that might be worth following up on.
- `HABITS`
- Habits of the speakers that could be worth replicating.
- `RECOMMENDATIONS`
- A list of things that the content recommends Habits of the speakers.
### Use cases
`extractwisdom` output can help you in multiple ways, including:
1. `Time Filtering`<br />
Allows you to quickly see if content is worth an in-depth review or not.
2. `Note Taking`<br />
Can be used as a substitute for taking time-consuming, manual notes on the content.
## Usage
You can reference the `extractwisdom` **system** and **user** content directly like so.
### Pull the _system_ prompt directly
```sh
curl -sS https://github.com/danielmiessler/fabric/blob/main/extract-wisdom/dmiessler/extract-wisdom-1.0.0/system.md
```
### Pull the _user_ prompt directly
```sh
curl -sS https://github.com/danielmiessler/fabric/blob/main/extract-wisdom/dmiessler/extract-wisdom-1.0.0/user.md
```
## Output
Here's an abridged ouptut example from `extractwisdom` (limited to only 10 items per section).
```markdown
## SUMMARY:
The content features a conversation between two individuals discussing various topics, including the decline of Western culture, the importance of beauty and subtlety in life, the impact of technology and AI, the resonance of Rilke's poetry, the value of deep reading and revisiting texts, the captivating nature of Ayn Rand's writing, the role of philosophy in understanding the world, and the influence of drugs on society. They also touch upon creativity, attention spans, and the importance of introspection.
## IDEAS:
1. Western culture is perceived to be declining due to a loss of values and an embrace of mediocrity.
2. Mass media and technology have contributed to shorter attention spans and a need for constant stimulation.
3. Rilke's poetry resonates due to its focus on beauty and ecstasy in everyday objects.
4. Subtlety is often overlooked in modern society due to sensory overload.
5. The role of technology in shaping music and performance art is significant.
6. Reading habits have shifted from deep, repetitive reading to consuming large quantities of new material.
7. Revisiting influential books as one ages can lead to new insights based on accumulated wisdom and experiences.
8. Fiction can vividly illustrate philosophical concepts through characters and narratives.
9. Many influential thinkers have backgrounds in philosophy, highlighting its importance in shaping reasoning skills.
10. Philosophy is seen as a bridge between theology and science, asking questions that both fields seek to answer.
## QUOTES:
1. "You can't necessarily think yourself into the answers. You have to create space for the answers to come to you."
2. "The West is dying and we are killing her."
3. "The American Dream has been replaced by mass packaged mediocrity porn, encouraging us to revel like happy pigs in our own meekness."
4. "There's just not that many people who have the courage to reach beyond consensus and go explore new ideas."
5. "I'll start watching Netflix when I've read the whole of human history."
6. "Rilke saw beauty in everything... He sees it's in one little thing, a representation of all things that are beautiful."
7. "Vanilla is a very subtle flavor... it speaks to sort of the sensory overload of the modern age."
8. "When you memorize chapters [of the Bible], it takes a few months, but you really understand how things are structured."
9. "As you get older, if there's books that moved you when you were younger, it's worth going back and rereading them."
10. "She [Ayn Rand] took complicated philosophy and embodied it in a way that anybody could resonate with."
## HABITS:
1. Avoiding mainstream media consumption for deeper engagement with historical texts and personal research.
2. Regularly revisiting influential books from youth to gain new insights with age.
3. Engaging in deep reading practices rather than skimming or speed-reading material.
4. Memorizing entire chapters or passages from significant texts for better understanding.
5. Disengaging from social media and fast-paced news cycles for more focused thought processes.
6. Walking long distances as a form of meditation and reflection.
7. Creating space for thoughts to solidify through introspection and stillness.
8. Embracing emotions such as grief or anger fully rather than suppressing them.
9. Seeking out varied experiences across different careers and lifestyles.
10. Prioritizing curiosity-driven research without specific goals or constraints.
## FACTS:
1. The West is perceived as declining due to cultural shifts away from traditional values.
2. Attention spans have shortened due to technological advancements and media consumption habits.
3. Rilke's poetry emphasizes finding beauty in everyday objects through detailed observation.
4. Modern society often overlooks subtlety due to sensory overload from various stimuli.
5. Reading habits have evolved from deep engagement with texts to consuming large quantities quickly.
6. Revisiting influential books can lead to new insights based on accumulated life experiences.
7. Fiction can effectively illustrate philosophical concepts through character development and narrative arcs.
8. Philosophy plays a significant role in shaping reasoning skills and understanding complex ideas.
9. Creativity may be stifled by cultural nihilism and protectionist attitudes within society.
10. Short-term thinking undermines efforts to create lasting works of beauty or significance.
## REFERENCES:
1. Rainer Maria Rilke's poetry
2. Netflix
3. Underworld concert
4. Katy Perry's theatrical performances
5. Taylor Swift's performances
6. Bible study
7. Atlas Shrugged by Ayn Rand
8. Robert Pirsig's writings
9. Bertrand Russell's definition of philosophy
10. Nietzsche's walks
```
This allows you to quickly extract what's valuable and meaningful from the content for the use cases above.
## Meta
- **Author**: Daniel Miessler
- **Version Information**: Daniel's main `extractwisdom` version.
- **Published**: January 5, 2024

View File

@@ -0,0 +1,29 @@
# IDENTITY and PURPOSE
You are a wisdom extraction service for text content. You are interested in wisdom related to the purpose and meaning of life, the role of technology in the future of humanity, artificial intelligence, memes, learning, reading, books, continuous improvement, and similar topics.
Take a step back and think step by step about how to achieve the best result possible as defined in the steps below. You have a lot of freedom to make this work well.
## OUTPUT SECTIONS
1. You extract a summary of the content in 50 words or less, including who is presenting and the content being discussed into a section called SUMMARY.
2. You extract the top 50 ideas from the input in a section called IDEAS:. If there are less than 50 then collect all of them.
3. You extract the 15-30 most insightful and interesting quotes from the input into a section called QUOTES:. Use the exact quote text from the input.
4. You extract 15-30 personal habits of the speakers, or mentioned by the speakers, in the connt into a section called HABITS. Examples include but aren't limited to: sleep schedule, reading habits, things the
5. You extract the 15-30 most insightful and interesting valid facts about the greater world that were mentioned in the content into a section called FACTS:.
6. You extract all mentions of writing, art, and other sources of inspiration mentioned by the speakers into a section called REFERENCES. This should include any and all references to something that the speake
7. You extract the 15-30 most insightful and interesting overall (not content recommendations from EXPLORE) recommendations that can be collected from the content into a section called RECOMMENDATIONS.
## OUTPUT INSTRUCTIONS
1. You only output Markdown.
2. Do not give warnings or notes; only output the requested sections.
3. You use numberd lists, not bullets.
4. Do not repeat ideas, quotes, facts, or resources.
5. Do not start items with the same opening words.

View File

@@ -0,0 +1 @@
CONTENT:

View File

@@ -0,0 +1,33 @@
# IDENTITY and PURPOSE
You extract surprising, insightful, and interesting information from text content.
Take a step back and think step-by-step about how to achieve the best possible results by following the steps below.
# STEPS
1. Extract a summary of the content in 25 words or less, including who created it and the content being discussed into a section called SUMMARY.
2. 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.
3. Extract 15 to 30 of the most surprising, insightful, and/or interesting quotes from the input into a section called QUOTES:. Use the exact quote text from the input.
4. Extract 15 to 30 of the most surprising, insightful, and/or interesting valid facts about the greater world that were mentioned in the content into a section called FACTS:.
5. Extract all mentions of writing, art, tools, projects and other sources of inspiration mentioned by the speakers into a section called REFERENCES. This should include any and all references to something that the speaker mentioned.
6. Extract the 15 to 30 of the most surprising, insightful, and/or interesting recommendations that can be collected from the content into a section called RECOMMENDATIONS.
# OUTPUT INSTRUCTIONS
- Only output Markdown.
- Extract at least 10 items for the other output sections.
- 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:

View File

@@ -0,0 +1 @@
CONTENT:

View File

@@ -35,7 +35,8 @@ END EXAMPLE PAUL GRAHAM ESSAY
# OUTPUT FORMAT
- Output a full, publish-ready essay using the instructions provided
- Do not use cliches or jargon in the essay.
- Write in Paul Graham's simple, plain, clear, and conversational style, not in a grandiose or academic style.
- Do not use cliches or jargon.
- Do not include common setup language in any sentence, including: in conclusion, in closing, etc.
- Do not output warnings or notes—just the output requested.

13
poetry.lock generated
View File

@@ -933,6 +933,17 @@ files = [
[package.dependencies]
typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0"
[[package]]
name = "pydub"
version = "0.25.1"
description = "Manipulate audio with an simple and easy high level interface"
optional = false
python-versions = "*"
files = [
{file = "pydub-0.25.1-py2.py3-none-any.whl", hash = "sha256:65617e33033874b59d87db603aa1ed450633288aefead953b30bded59cb599a6"},
{file = "pydub-0.25.1.tar.gz", hash = "sha256:980a33ce9949cab2a569606b65674d748ecbca4f0796887fd6f46173a7b0d30f"},
]
[[package]]
name = "pyjwt"
version = "2.8.0"
@@ -1394,4 +1405,4 @@ testing = ["coverage (>=5.0.3)", "zope.event", "zope.testing"]
[metadata]
lock-version = "2.0"
python-versions = "^3.10"
content-hash = "8aa1e3fe70b9d326a7809abd70f2d78fee286d5106ab40f7d2d61a7feaf359ef"
content-hash = "b8025aa005b3ad74c5e76f766c9311f2fa0592d4672e7f6e328d5f27001554aa"

View File

@@ -32,6 +32,7 @@ gunicorn = "^21.2.0"
gevent = "^23.9.1"
httpx = "^0.26.0"
tqdm = "^4.66.1"
pydub = "^0.25.1"
[tool.poetry.group.server.dependencies]

View File

@@ -1,5 +1,12 @@
#!/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
@@ -7,8 +14,12 @@ poetry install
# List of commands to check and add or update alias for
commands=("fabric" "fabric-api" "fabric-webui")
# List of shell configuration files to update
config_files=(~/.bashrc ~/.zshrc ~/.bash_profile)
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
@@ -16,22 +27,46 @@ for config_file in "${config_files[@]}"; do
echo "Updating $config_file"
for cmd in "${commands[@]}"; do
# Get the path of the command
CMD_PATH=$(poetry run which $cmd)
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 -q "alias $cmd=" "$config_file"; then
# Replace the existing alias with the new one
sed -i "/alias $cmd=/c\alias $cmd='$CMD_PATH'" "$config_file"
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 -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
echo "Please close this terminal window to have new aliases work."
# 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