mirror of
https://github.com/danielmiessler/Fabric.git
synced 2026-01-09 22:38:10 -05:00
Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7eed80710e | ||
|
|
fbd62be47d | ||
|
|
85cc7b8a9d | ||
|
|
0eee89140c | ||
|
|
5571e6fafd | ||
|
|
9a4e920618 | ||
|
|
6e479999b1 | ||
|
|
f65f2501b4 | ||
|
|
4b12bd2a61 | ||
|
|
d83a3beeeb | ||
|
|
7428c8017f | ||
|
|
008ed76d37 | ||
|
|
ce9d4ad831 | ||
|
|
657bcab48c | ||
|
|
cd11dcc7a9 | ||
|
|
22040a42f2 | ||
|
|
705ccd750b | ||
|
|
db7c2b70cb | ||
|
|
9dc9bfa1d5 | ||
|
|
6b93658191 | ||
|
|
ea7a425a26 | ||
|
|
9582978adb | ||
|
|
453d8e75e4 | ||
|
|
901a010efd | ||
|
|
b5c2d069f2 | ||
|
|
f744e25b39 | ||
|
|
096f40df68 |
@@ -122,7 +122,7 @@
|
||||
},
|
||||
{
|
||||
"patternName": "analyze_threat_report_trends",
|
||||
"pattern_extract": "# IDENTITY and PURPOSE\n\nYou are a super-intelligent cybersecurity expert. You specialize in extracting the surprising, insightful, and interesting information from cybersecurity threat reports.\n\nTake a step back and think step-by-step about how to achieve the best possible results by following the steps below.\n\n# STEPS\n\n- Read the entire threat report from an expert perspective, thinking deeply about what's new, interesting, and surprising in the report.\n\n- 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.\n\n# OUTPUT INSTRUCTIONS\n\n- Only output Markdown.\n- Do not output the markdown code syntax, only the content.\n- Do not use bold or italics formatting in the markdown output.\n- Extract at least 20 TRENDS from the content.\n- Do not give warnings or notes; only output the requested sections.\n- You use bulleted lists for output, not numbered lists.\n- Do not repeat ideas, quotes, facts, or resources.\n- Do not start items with the same opening words.\n- Ensure you follow ALL these instructions when creating your output.\n\n# INPUT"
|
||||
"pattern_extract": "# IDENTITY and PURPOSE\n\nYou are a super-intelligent cybersecurity expert. You specialize in extracting the surprising, insightful, and interesting information from cybersecurity threat reports.\n\nTake a step back and think step-by-step about how to achieve the best possible results by following the steps below.\n\n# STEPS\n\n- Read the entire threat report from an expert perspective, thinking deeply about what's new, interesting, and surprising in the report.\n\n- 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.\n\n# OUTPUT INSTRUCTIONS\n\n- Only output Markdown.\n- Do not output the markdown code syntax, only the content.\n- Do not use bold or italics formatting in the markdown output.\n- Extract at least 20 TRENDS from the content.\n- Do not give warnings or notes; only output the requested sections.\n- You use bulleted lists for output, not numbered lists.\n- Do not repeat trends.\n- Do not start items with the same opening words.\n- Ensure you follow ALL these instructions when creating your output.\n\n# INPUT"
|
||||
},
|
||||
{
|
||||
"patternName": "answer_interview_question",
|
||||
@@ -402,7 +402,7 @@
|
||||
},
|
||||
{
|
||||
"patternName": "extract_business_ideas",
|
||||
"pattern_extract": "# IDENTITY and PURPOSE\n\nYou are a business idea extraction assistant. You are extremely interested in business ideas that could revolutionize or just overhaul existing or new industries.\n\nTake a deep breath 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.\n\n## OUTPUT SECTIONS\n\n1. You extract all the top business ideas from the content. It might be a few or it might be up to 40 in a section called EXTRACTED_IDEAS\n\n2. Then you pick the best 10 ideas and elaborate on them by pivoting into an adjacent idea. This will be ELABORATED_IDEAS. They should each be unique and have an interesting differentiator.\n\n## OUTPUT INSTRUCTIONS\n\n1. You only output Markdown.\n2. Do not give warnings or notes; only output the requested sections.\n3. You use numbered lists, not bullets.\n4. Do not repeat ideas, quotes, facts, or resources.\n5. Do not start items in the lists with the same opening words.\n\n# INPUT:\n\nINPUT:"
|
||||
"pattern_extract": "# IDENTITY and PURPOSE\n\nYou are a business idea extraction assistant. You are extremely interested in business ideas that could revolutionize or just overhaul existing or new industries.\n\nTake a deep breath 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.\n\n## OUTPUT SECTIONS\n\n1. You extract all the top business ideas from the content. It might be a few or it might be up to 40 in a section called EXTRACTED_IDEAS\n\n2. Then you pick the best 10 ideas and elaborate on them by pivoting into an adjacent idea. This will be ELABORATED_IDEAS. They should each be unique and have an interesting differentiator.\n\n## OUTPUT INSTRUCTIONS\n\n1. You only output Markdown.\n2. Do not give warnings or notes; only output the requested sections.\n3. You use numbered lists, not bullets.\n4. Do not repeat ideas.\n5. Do not start items in the lists with the same opening words.\n\n# INPUT:\n\nINPUT:"
|
||||
},
|
||||
{
|
||||
"patternName": "extract_controversial_ideas",
|
||||
@@ -438,7 +438,7 @@
|
||||
},
|
||||
{
|
||||
"patternName": "extract_jokes",
|
||||
"pattern_extract": "# IDENTITY and PURPOSE\n\nYou extract jokes from text content. You are interested only in jokes.\n\nYou create bullet points that capture the joke and punchline.\n\n# OUTPUT INSTRUCTIONS\n\n- Only output Markdown.\n\n- Only extract jokes.\n\n- Each bullet should should have the joke followed by punchline on the next line.\n\n- Do not give warnings or notes; only output the requested sections.\n\n- You use bulleted lists for output, not numbered lists.\n\n- Do not repeat jokes, quotes, facts, or resources.\n\n- Ensure you follow ALL these instructions when creating your output.\n\n\n# INPUT\n"
|
||||
"pattern_extract": "# IDENTITY and PURPOSE\n\nYou extract jokes from text content. You are interested only in jokes.\n\nYou create bullet points that capture the joke and punchline.\n\n# OUTPUT INSTRUCTIONS\n\n- Only output Markdown.\n\n- Only extract jokes.\n\n- Each bullet should should have the joke followed by punchline on the next line.\n\n- Do not give warnings or notes; only output the requested sections.\n\n- You use bulleted lists for output, not numbered lists.\n\n- Do not repeat jokes.\n\n- Ensure you follow ALL these instructions when creating your output.\n\n\n# INPUT\n"
|
||||
},
|
||||
{
|
||||
"patternName": "extract_latest_video",
|
||||
@@ -446,7 +446,7 @@
|
||||
},
|
||||
{
|
||||
"patternName": "extract_main_idea",
|
||||
"pattern_extract": "# IDENTITY and PURPOSE\n\nYou extract the primary and/or most surprising, insightful, and interesting idea from any input.\n\nTake a step back and think step-by-step about how to achieve the best possible results by following the steps below.\n\n# STEPS\n\n- Fully digest the content provided.\n\n- Extract the most important idea from the content.\n\n- In a section called MAIN IDEA, write a 15-word sentence that captures the main idea.\n\n- In a section called MAIN RECOMMENDATION, write a 15-word sentence that captures what's recommended for people to do based on the idea.\n\n# OUTPUT INSTRUCTIONS\n\n- Only output Markdown.\n- Do not give warnings or notes; only output the requested sections.\n- Do not repeat ideas, quotes, facts, or resources.\n- Do not start items with the same opening words.\n- Ensure you follow ALL these instructions when creating your output.\n\n# INPUT"
|
||||
"pattern_extract": "# IDENTITY and PURPOSE\n\nYou extract the primary and/or most surprising, insightful, and interesting idea from any input.\n\nTake a step back and think step-by-step about how to achieve the best possible results by following the steps below.\n\n# STEPS\n\n- Fully digest the content provided.\n\n- Extract the most important idea from the content.\n\n- In a section called MAIN IDEA, write a 15-word sentence that captures the main idea.\n\n- In a section called MAIN RECOMMENDATION, write a 15-word sentence that captures what's recommended for people to do based on the idea.\n\n# OUTPUT INSTRUCTIONS\n\n- Only output Markdown.\n- Do not give warnings or notes; only output the requested sections.\n- Do not start items with the same opening words.\n- Ensure you follow ALL these instructions when creating your output.\n\n# INPUT"
|
||||
},
|
||||
{
|
||||
"patternName": "extract_most_redeeming_thing",
|
||||
@@ -474,7 +474,7 @@
|
||||
},
|
||||
{
|
||||
"patternName": "extract_product_features",
|
||||
"pattern_extract": "# IDENTITY and PURPOSE\n\nYou extract the list of product features from the input.\n\nTake a step back and think step-by-step about how to achieve the best possible results by following the steps below.\n\n# STEPS\n\n- Consume the whole input as a whole and think about the type of announcement or content it is.\n\n- Figure out which parts were talking about features of a product or service.\n\n- Output the list of features as a bulleted list of 16 words per bullet.\n\n# OUTPUT INSTRUCTIONS\n\n- Only output Markdown.\n\n- Do not give warnings or notes; only output the requested sections.\n\n- You use bulleted lists for output, not numbered lists.\n\n- Do not repeat ideas, quotes, facts, or resources.\n\n- Do not start items with the same opening words."
|
||||
"pattern_extract": "# IDENTITY and PURPOSE\n\nYou extract the list of product features from the input.\n\nTake a step back and think step-by-step about how to achieve the best possible results by following the steps below.\n\n# STEPS\n\n- Consume the whole input as a whole and think about the type of announcement or content it is.\n\n- Figure out which parts were talking about features of a product or service.\n\n- Output the list of features as a bulleted list of 16 words per bullet.\n\n# OUTPUT INSTRUCTIONS\n\n- Only output Markdown.\n\n- Do not give warnings or notes; only output the requested sections.\n\n- You use bulleted lists for output, not numbered lists.\n\n- Do not repeat features.\n\n- Do not start items with the same opening words."
|
||||
},
|
||||
{
|
||||
"patternName": "extract_questions",
|
||||
|
||||
143
README.md
143
README.md
@@ -34,13 +34,18 @@
|
||||
- [`fabric`](#fabric)
|
||||
- [Navigation](#navigation)
|
||||
- [Updates](#updates)
|
||||
- [Intro videos](#intro-videos)
|
||||
- [What and why](#what-and-why)
|
||||
- [Intro videos](#intro-videos)
|
||||
- [Philosophy](#philosophy)
|
||||
- [Breaking problems into components](#breaking-problems-into-components)
|
||||
- [Too many prompts](#too-many-prompts)
|
||||
- [Installation](#installation)
|
||||
- [Get Latest Release Binaries](#get-latest-release-binaries)
|
||||
- [Windows:](#windows)
|
||||
- [MacOS (arm64):](#macos-arm64)
|
||||
- [MacOS (amd64):](#macos-amd64)
|
||||
- [Linux (amd64):](#linux-amd64)
|
||||
- [Linux (arm64):](#linux-arm64)
|
||||
- [From Source](#from-source)
|
||||
- [Environment Variables](#environment-variables)
|
||||
- [Setup](#setup)
|
||||
@@ -52,12 +57,15 @@
|
||||
- [Our approach to prompting](#our-approach-to-prompting)
|
||||
- [Examples](#examples)
|
||||
- [Just use the Patterns](#just-use-the-patterns)
|
||||
- [Prompt Strategies](#prompt-strategies)
|
||||
- [Custom Patterns](#custom-patterns)
|
||||
- [Helper Apps](#helper-apps)
|
||||
- [`to_pdf`](#to_pdf)
|
||||
- [`to_pdf` Installation](#to_pdf-installation)
|
||||
- [pbpaste](#pbpaste)
|
||||
- [Web Interface](#Web_Interface)
|
||||
- [Web Interface](#web-interface)
|
||||
- [Installing](#installing)
|
||||
- [Streamlit UI](#streamlit-ui)
|
||||
- [Meta](#meta)
|
||||
- [Primary contributors](#primary-contributors)
|
||||
|
||||
@@ -341,11 +349,6 @@ for pattern_file in ~/.config/fabric/patterns/*; do
|
||||
}
|
||||
"
|
||||
done
|
||||
|
||||
yt() {
|
||||
local video_link="$1"
|
||||
fabric -y "$video_link" --transcript
|
||||
}
|
||||
```
|
||||
|
||||
This will allow you to use the patterns as aliases like in the above for example `summarize` instead of `fabric --pattern summarize --stream`, however if you pass in an extra argument like this `summarize "my_article_title"` your output will be saved in the destination that you set in `obsidian_base="/path/to/obsidian"` in the following format `YYYY-MM-DD-my_article_title.md` where the date gets autogenerated for you.
|
||||
@@ -391,48 +394,60 @@ Usage:
|
||||
fabric [OPTIONS]
|
||||
|
||||
Application Options:
|
||||
-p, --pattern= Choose a pattern from the available patterns
|
||||
-v, --variable= Values for pattern variables, e.g. -v=#role:expert -v=#points:30"
|
||||
-C, --context= Choose a context from the available contexts
|
||||
--session= Choose a session from the available sessions
|
||||
-a, --attachment= Attachment path or URL (e.g. for OpenAI image recognition messages)
|
||||
-S, --setup Run setup for all reconfigurable parts of fabric
|
||||
-t, --temperature= Set temperature (default: 0.7)
|
||||
-T, --topp= Set top P (default: 0.9)
|
||||
-s, --stream Stream
|
||||
-P, --presencepenalty= Set presence penalty (default: 0.0)
|
||||
-r, --raw Use the defaults of the model without sending chat options (like temperature etc.) and use the user role instead of the system role for patterns.
|
||||
-F, --frequencypenalty= Set frequency penalty (default: 0.0)
|
||||
-l, --listpatterns List all patterns
|
||||
-L, --listmodels List all available models
|
||||
-x, --listcontexts List all contexts
|
||||
-X, --listsessions List all sessions
|
||||
-U, --updatepatterns Update patterns
|
||||
-c, --copy Copy to clipboard
|
||||
-m, --model= Choose model
|
||||
-o, --output= Output to file
|
||||
--output-session Output the entire session (also a temporary one) to the output file
|
||||
-n, --latest= Number of latest patterns to list (default: 0)
|
||||
-d, --changeDefaultModel Change default model
|
||||
-y, --youtube= YouTube video "URL" to grab transcript, comments from it and send to chat
|
||||
--transcript Grab transcript from YouTube video and send to chat (it used per default).
|
||||
--comments Grab comments from YouTube video and send to chat
|
||||
--metadata Grab metadata from YouTube video and send to chat
|
||||
-g, --language= Specify the Language Code for the chat, e.g. -g=en -g=zh
|
||||
-u, --scrape_url= Scrape website URL to markdown using Jina AI
|
||||
-q, --scrape_question= Search question using Jina AI
|
||||
-e, --seed= Seed to be used for LMM generation
|
||||
-w, --wipecontext= Wipe context
|
||||
-W, --wipesession= Wipe session
|
||||
--printcontext= Print context
|
||||
--printsession= Print session
|
||||
--readability Convert HTML input into a clean, readable view
|
||||
--serve Initiate the API server
|
||||
--dry-run Show what would be sent to the model without actually sending it
|
||||
--version Print current version
|
||||
-p, --pattern= Choose a pattern from the available patterns
|
||||
-v, --variable= Values for pattern variables, e.g. -v=#role:expert -v=#points:30
|
||||
-C, --context= Choose a context from the available contexts
|
||||
--session= Choose a session from the available sessions
|
||||
-a, --attachment= Attachment path or URL (e.g. for OpenAI image recognition messages)
|
||||
-S, --setup Run setup for all reconfigurable parts of fabric
|
||||
-t, --temperature= Set temperature (default: 0.7)
|
||||
-T, --topp= Set top P (default: 0.9)
|
||||
-s, --stream Stream
|
||||
-P, --presencepenalty= Set presence penalty (default: 0.0)
|
||||
-r, --raw Use the defaults of the model without sending chat options (like temperature etc.) and use the user role instead of the system role for patterns.
|
||||
-F, --frequencypenalty= Set frequency penalty (default: 0.0)
|
||||
-l, --listpatterns List all patterns
|
||||
-L, --listmodels List all available models
|
||||
-x, --listcontexts List all contexts
|
||||
-X, --listsessions List all sessions
|
||||
-U, --updatepatterns Update patterns
|
||||
-c, --copy Copy to clipboard
|
||||
-m, --model= Choose model
|
||||
--modelContextLength= Model context length (only affects ollama)
|
||||
-o, --output= Output to file
|
||||
--output-session Output the entire session (also a temporary one) to the output file
|
||||
-n, --latest= Number of latest patterns to list (default: 0)
|
||||
-d, --changeDefaultModel Change default model
|
||||
-y, --youtube= YouTube video or play list "URL" to grab transcript, comments from it and send to chat or print it put to the console and store it in the output file
|
||||
--playlist Prefer playlist over video if both ids are present in the URL
|
||||
--transcript Grab transcript from YouTube video and send to chat (it is used per default).
|
||||
--transcript-with-timestamps Grab transcript from YouTube video with timestamps and send to chat
|
||||
--comments Grab comments from YouTube video and send to chat
|
||||
--metadata Output video metadata
|
||||
-g, --language= Specify the Language Code for the chat, e.g. -g=en -g=zh
|
||||
-u, --scrape_url= Scrape website URL to markdown using Jina AI
|
||||
-q, --scrape_question= Search question using Jina AI
|
||||
-e, --seed= Seed to be used for LMM generation
|
||||
-w, --wipecontext= Wipe context
|
||||
-W, --wipesession= Wipe session
|
||||
--printcontext= Print context
|
||||
--printsession= Print session
|
||||
--readability Convert HTML input into a clean, readable view
|
||||
--input-has-vars Apply variables to user input
|
||||
--dry-run Show what would be sent to the model without actually sending it
|
||||
--serve Serve the Fabric Rest API
|
||||
--serveOllama Serve the Fabric Rest API with ollama endpoints
|
||||
--address= The address to bind the REST API (default: :8080)
|
||||
--config= Path to YAML config file
|
||||
--version Print current version
|
||||
--listextensions List all registered extensions
|
||||
--addextension= Register a new extension from config file path
|
||||
--rmextension= Remove a registered extension by name
|
||||
--strategy= Choose a strategy from the available strategies
|
||||
--liststrategies List all strategies
|
||||
|
||||
Help Options:
|
||||
-h, --help Show this help message
|
||||
-h, --help Show this help message
|
||||
|
||||
```
|
||||
|
||||
@@ -503,6 +518,21 @@ You can use any of the Patterns you see there in any AI application that you hav
|
||||
|
||||
The wisdom of crowds for the win.
|
||||
|
||||
### Prompt Strategies
|
||||
|
||||
Fabric also implements prompt strategies like "Chain of Thought" or "Chain of Draft" which can
|
||||
be used in addition to the basic patterns.
|
||||
|
||||
See the [Thinking Faster by Writing Less](https://arxiv.org/pdf/2502.18600) paper and
|
||||
the [Thought Generation section of Learn Prompting](https://learnprompting.org/docs/advanced/thought_generation/introduction) for examples of prompt strategies.
|
||||
|
||||
Each strategy is available as a small `json` file in the [`/strategies`](https://github.com/danielmiessler/fabric/tree/main/strategies) directory.
|
||||
|
||||
The prompt modification of the strategy is applied to the system prompt and passed on to the
|
||||
LLM in the chat session.
|
||||
|
||||
Use `fabric -S` and select the option to install the strategies in your `~/.config/fabric` directory.
|
||||
|
||||
## Custom Patterns
|
||||
|
||||
You may want to use Fabric to create your own custom Patterns—but not share them with others. No problem!
|
||||
@@ -575,16 +605,16 @@ alias pbpaste='xclip -selection clipboard -o'
|
||||
|
||||
## Web Interface
|
||||
|
||||
Fabric now includes a built-in web interface that provides a GUI alternative to the command-line interface and an out-of-the-box website for those who want to get started with web development or blogging.
|
||||
Fabric now includes a built-in web interface that provides a GUI alternative to the command-line interface and an out-of-the-box website for those who want to get started with web development or blogging.
|
||||
You can use this app as a GUI interface for Fabric, a ready to go blog-site, or a website template for your own projects.
|
||||
|
||||
The `web/src/lib/content` directory includes starter `.obsidian/` and `templates/` directories, allowing you to open up the `web/src/lib/content/` directory as an [Obsidian.md](https://obsidian.md) vault. You can place your posts in the posts directory when you're ready to publish.
|
||||
|
||||
### Installing
|
||||
|
||||
The GUI can be installed by navigating to the `web` directory and using `npm install`, `pnpm install`, or your favorite package manager. Then simply run the development server to start the app.
|
||||
The GUI can be installed by navigating to the `web` directory and using `npm install`, `pnpm install`, or your favorite package manager. Then simply run the development server to start the app.
|
||||
|
||||
_You will need to run fabric in a separate terminal with the `fabric --serve` command._
|
||||
_You will need to run fabric in a separate terminal with the `fabric --serve` command._
|
||||
|
||||
**From the fabric project `web/` directory:**
|
||||
|
||||
@@ -604,7 +634,10 @@ To run the Streamlit user interface:
|
||||
|
||||
```bash
|
||||
# Install required dependencies
|
||||
pip install streamlit pandas matplotlib seaborn numpy python-dotenv
|
||||
pip install -r requirements.txt
|
||||
|
||||
# Or manually install dependencies
|
||||
pip install streamlit pandas matplotlib seaborn numpy python-dotenv pyperclip
|
||||
|
||||
# Run the Streamlit app
|
||||
streamlit run streamlit.py
|
||||
@@ -617,6 +650,14 @@ The Streamlit UI provides a user-friendly interface for:
|
||||
- Creating and editing patterns
|
||||
- Analyzing pattern results
|
||||
|
||||
#### Clipboard Support
|
||||
|
||||
The Streamlit UI supports clipboard operations across different platforms:
|
||||
|
||||
- **macOS**: Uses `pbcopy` and `pbpaste` (built-in)
|
||||
- **Windows**: Uses `pyperclip` library (install with `pip install pyperclip`)
|
||||
- **Linux**: Uses `xclip` (install with `sudo apt-get install xclip` or equivalent for your distro)
|
||||
|
||||
## Meta
|
||||
|
||||
> [!NOTE]
|
||||
|
||||
14
cli/cli.go
14
cli/cli.go
@@ -73,7 +73,10 @@ func Cli(version string) (err error) {
|
||||
}
|
||||
|
||||
if currentFlags.ChangeDefaultModel {
|
||||
err = registry.Defaults.Setup()
|
||||
if err = registry.Defaults.Setup(); err != nil {
|
||||
return
|
||||
}
|
||||
err = registry.SaveEnvFile()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -156,6 +159,11 @@ func Cli(version string) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
if currentFlags.ListStrategies {
|
||||
err = registry.Strategies.ListStrategies()
|
||||
return
|
||||
}
|
||||
|
||||
// if the interactive flag is set, run the interactive function
|
||||
// if currentFlags.Interactive {
|
||||
// interactive.Interactive()
|
||||
@@ -166,7 +174,7 @@ func Cli(version string) (err error) {
|
||||
var messageTools string
|
||||
|
||||
if currentFlags.YouTube != "" {
|
||||
if registry.YouTube.IsConfigured() == false {
|
||||
if !registry.YouTube.IsConfigured() {
|
||||
err = fmt.Errorf("YouTube is not configured, please run the setup procedure")
|
||||
return
|
||||
}
|
||||
@@ -241,7 +249,7 @@ func Cli(version string) (err error) {
|
||||
}
|
||||
|
||||
var chatter *core.Chatter
|
||||
if chatter, err = registry.GetChatter(currentFlags.Model, currentFlags.ModelContextLength, currentFlags.Stream, currentFlags.DryRun); err != nil {
|
||||
if chatter, err = registry.GetChatter(currentFlags.Model, currentFlags.ModelContextLength, currentFlags.Strategy, currentFlags.Stream, currentFlags.DryRun); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -69,6 +69,8 @@ type Flags struct {
|
||||
ListExtensions bool `long:"listextensions" description:"List all registered extensions"`
|
||||
AddExtension string `long:"addextension" description:"Register a new extension from config file path"`
|
||||
RemoveExtension string `long:"rmextension" description:"Remove a registered extension by name"`
|
||||
Strategy string `long:"strategy" description:"Choose a strategy from the available strategies" default:""`
|
||||
ListStrategies bool `long:"liststrategies" description:"List all strategies"`
|
||||
}
|
||||
|
||||
var debug = false
|
||||
@@ -267,13 +269,14 @@ func (o *Flags) BuildChatRequest(Meta string) (ret *common.ChatRequest, err erro
|
||||
ContextName: o.Context,
|
||||
SessionName: o.Session,
|
||||
PatternName: o.Pattern,
|
||||
StrategyName: o.Strategy,
|
||||
PatternVariables: o.PatternVariables,
|
||||
InputHasVars: o.InputHasVars,
|
||||
Meta: Meta,
|
||||
}
|
||||
|
||||
var message *goopenai.ChatCompletionMessage
|
||||
if o.Attachments == nil || len(o.Attachments) == 0 {
|
||||
if len(o.Attachments) == 0 {
|
||||
if o.Message != "" {
|
||||
message = &goopenai.ChatCompletionMessage{
|
||||
Role: goopenai.ChatMessageRoleUser,
|
||||
|
||||
@@ -13,6 +13,7 @@ type ChatRequest struct {
|
||||
Language string
|
||||
Meta string
|
||||
InputHasVars bool
|
||||
StrategyName string
|
||||
}
|
||||
|
||||
type ChatOptions struct {
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/danielmiessler/fabric/common"
|
||||
"github.com/danielmiessler/fabric/plugins/ai"
|
||||
"github.com/danielmiessler/fabric/plugins/db/fsdb"
|
||||
"github.com/danielmiessler/fabric/plugins/strategy"
|
||||
"github.com/danielmiessler/fabric/plugins/template"
|
||||
)
|
||||
|
||||
@@ -24,6 +25,7 @@ type Chatter struct {
|
||||
model string
|
||||
modelContextLength int
|
||||
vendor ai.Vendor
|
||||
strategy string
|
||||
}
|
||||
|
||||
func (o *Chatter) Send(request *common.ChatRequest, opts *common.ChatOptions) (session *fsdb.Session, err error) {
|
||||
@@ -35,6 +37,9 @@ func (o *Chatter) Send(request *common.ChatRequest, opts *common.ChatOptions) (s
|
||||
if len(vendorMessages) == 0 {
|
||||
if session.Name != "" {
|
||||
err = o.db.Sessions.SaveSession(session)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
err = fmt.Errorf("no messages provided")
|
||||
return
|
||||
@@ -140,6 +145,19 @@ func (o *Chatter) BuildSession(request *common.ChatRequest, raw bool) (session *
|
||||
}
|
||||
|
||||
systemMessage := strings.TrimSpace(contextContent) + strings.TrimSpace(patternContent)
|
||||
|
||||
// Apply strategy if specified
|
||||
if request.StrategyName != "" {
|
||||
strategy, err := strategy.LoadStrategy(request.StrategyName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not load strategy %s: %v", request.StrategyName, err)
|
||||
}
|
||||
if strategy != nil && strategy.Prompt != "" {
|
||||
// prepend the strategy prompt to the system message
|
||||
systemMessage = fmt.Sprintf("%s\n%s", strategy.Prompt, systemMessage)
|
||||
}
|
||||
}
|
||||
|
||||
if request.Language != "" {
|
||||
systemMessage = fmt.Sprintf("%s. Please use the language '%s' for the output.", systemMessage, request.Language)
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"strconv"
|
||||
|
||||
"github.com/danielmiessler/fabric/plugins/ai/exolab"
|
||||
"github.com/danielmiessler/fabric/plugins/strategy"
|
||||
|
||||
"github.com/samber/lo"
|
||||
|
||||
@@ -44,6 +45,7 @@ func NewPluginRegistry(db *fsdb.Db) (ret *PluginRegistry, err error) {
|
||||
YouTube: youtube.NewYouTube(),
|
||||
Language: lang.NewLanguage(),
|
||||
Jina: jina.NewClient(),
|
||||
Strategies: strategy.NewStrategiesManager(),
|
||||
}
|
||||
|
||||
var homedir string
|
||||
@@ -86,6 +88,7 @@ type PluginRegistry struct {
|
||||
Language *lang.Language
|
||||
Jina *jina.Client
|
||||
TemplateExtensions *template.ExtensionManager
|
||||
Strategies *strategy.StrategiesManager
|
||||
}
|
||||
|
||||
func (o *PluginRegistry) SaveEnvFile() (err error) {
|
||||
@@ -94,6 +97,7 @@ func (o *PluginRegistry) SaveEnvFile() (err error) {
|
||||
|
||||
o.Defaults.Settings.FillEnvFileContent(&envFileContent)
|
||||
o.PatternsLoader.SetupFillEnvFileContent(&envFileContent)
|
||||
o.Strategies.SetupFillEnvFileContent(&envFileContent)
|
||||
|
||||
for _, vendor := range o.VendorManager.Vendors {
|
||||
vendor.SetupFillEnvFileContent(&envFileContent)
|
||||
@@ -109,7 +113,7 @@ func (o *PluginRegistry) SaveEnvFile() (err error) {
|
||||
|
||||
func (o *PluginRegistry) Setup() (err error) {
|
||||
setupQuestion := plugins.NewSetupQuestion("Enter the number of the plugin to setup")
|
||||
groupsPlugins := common.NewGroupsItemsSelector[plugins.Plugin]("Available plugins (please configure all required plugins):",
|
||||
groupsPlugins := common.NewGroupsItemsSelector("Available plugins (please configure all required plugins):",
|
||||
func(plugin plugins.Plugin) string {
|
||||
var configuredLabel string
|
||||
if plugin.IsConfigured() {
|
||||
@@ -125,7 +129,7 @@ func (o *PluginRegistry) Setup() (err error) {
|
||||
return vendor
|
||||
})...)
|
||||
|
||||
groupsPlugins.AddGroupItems("Tools", o.Defaults, o.PatternsLoader, o.YouTube, o.Language, o.Jina)
|
||||
groupsPlugins.AddGroupItems("Tools", o.Defaults, o.PatternsLoader, o.YouTube, o.Language, o.Jina, o.Strategies)
|
||||
|
||||
for {
|
||||
groupsPlugins.Print()
|
||||
@@ -206,7 +210,7 @@ func (o *PluginRegistry) Configure() (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (o *PluginRegistry) GetChatter(model string, modelContextLength int, stream bool, dryRun bool) (ret *Chatter, err error) {
|
||||
func (o *PluginRegistry) GetChatter(model string, modelContextLength int, strategy string, stream bool, dryRun bool) (ret *Chatter, err error) {
|
||||
ret = &Chatter{
|
||||
db: o.Db,
|
||||
Stream: stream,
|
||||
@@ -258,5 +262,6 @@ func (o *PluginRegistry) GetChatter(model string, modelContextLength int, stream
|
||||
model, defaultModel, defaultVendor, errMsg)
|
||||
return
|
||||
}
|
||||
ret.strategy = strategy
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
"1.4.156"
|
||||
"1.4.162"
|
||||
|
||||
@@ -24,7 +24,7 @@ Extract at least basic information about the malware.
|
||||
Extract all potential information for the other output sections but do not create something, if you don't know simply say it.
|
||||
Do not give warnings or notes; only output the requested sections.
|
||||
You use bulleted lists for output, not numbered lists.
|
||||
Do not repeat ideas, facts, or resources.
|
||||
Do not repeat references.
|
||||
Do not start items with the same opening words.
|
||||
Ensure you follow ALL these instructions when creating your output.
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ Take a step back and think step-by-step about how to achieve the best possible r
|
||||
- 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 repeat trends, statistics, quotes, or references.
|
||||
- Do not start items with the same opening words.
|
||||
- Ensure you follow ALL these instructions when creating your output.
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ Take a step back and think step-by-step about how to achieve the best possible r
|
||||
- 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 repeat trends.
|
||||
- Do not start items with the same opening words.
|
||||
- Ensure you follow ALL these instructions when creating your output.
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ 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 repeat ideas, habits, facts, or insights.
|
||||
|
||||
Do not start items with the same opening words.
|
||||
|
||||
|
||||
14
patterns/create_flash_cards/system.md
Normal file
14
patterns/create_flash_cards/system.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# IDENTITY
|
||||
|
||||
You are an expert educator AI with a 4,221 IQ. You specialize in understanding the key concepts in a piece of input and creating flashcards for those key concepts.
|
||||
|
||||
# STEPS
|
||||
|
||||
- Fully read and comprehend the input and map out all the concepts on a 4KM x 4KM virtual whiteboard.
|
||||
- Make a list of the key concepts, definitions, terms, etc. that are associated with the input.
|
||||
- Create flashcards for each key concept, definition, term, etc. that you have identified.
|
||||
- The flashcard should be a question of 8-16 words and an answer of up to 32 words.
|
||||
|
||||
# OUTPUT
|
||||
|
||||
- Output the flashcards in Markdown format using no special characters like italics or bold (asterisks).
|
||||
@@ -27,7 +27,7 @@ Take a step back and think step-by-step about how to achieve the best possible r
|
||||
- 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 repeat insights, trends, or quotes.
|
||||
- Do not start items with the same opening words.
|
||||
- Ensure you follow ALL these instructions when creating your output.
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ Take a step back and think step-by-step about how to achieve the best possible r
|
||||
- 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 repeat quotes, or references.
|
||||
- Do not start items with the same opening words.
|
||||
- Ensure you follow ALL these instructions when creating your output.
|
||||
|
||||
|
||||
@@ -25,5 +25,5 @@ Take a step back and think step by step about how to achieve the best result pos
|
||||
1. You only output Markdown.
|
||||
2. Do not give warnings or notes; only output the requested sections.
|
||||
3. You use numbered lists, not bullets.
|
||||
4. Do not repeat ideas, quotes, facts, or resources.
|
||||
4. Do not repeat ideas, quotes, habits, facts, or references.
|
||||
5. Do not start items with the same opening words.
|
||||
|
||||
@@ -24,7 +24,7 @@ Take a step back and think step-by-step about how to achieve the best possible r
|
||||
- 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 repeat ideas, quotes, facts, or references.
|
||||
- Do not start items with the same opening words.
|
||||
- Ensure you follow ALL these instructions when creating your output.
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ Take a deep breath and think step by step about how to achieve the best result p
|
||||
1. You only output Markdown.
|
||||
2. Do not give warnings or notes; only output the requested sections.
|
||||
3. You use numbered lists, not bullets.
|
||||
4. Do not repeat ideas, quotes, facts, or resources.
|
||||
4. Do not repeat ideas.
|
||||
5. Do not start items in the lists with the same opening words.
|
||||
|
||||
# INPUT:
|
||||
|
||||
@@ -24,7 +24,7 @@ Take a step back and think step-by-step about how to achieve the best possible r
|
||||
|
||||
- You use bulleted lists for output, not numbered lists.
|
||||
|
||||
- Do not repeat ideas, quotes, facts, or resources.
|
||||
- Do not repeat vulnerabilities, or references.
|
||||
|
||||
- Do not start items with the same opening words.
|
||||
|
||||
|
||||
@@ -175,7 +175,7 @@ END OUTPUT EXAMPLE
|
||||
|
||||
- You use bulleted lists for output, not numbered lists.
|
||||
|
||||
- Do not repeat ideas, quotes, facts, or resources.
|
||||
- Do not repeat insights.
|
||||
|
||||
- Do not start items with the same opening words.
|
||||
|
||||
|
||||
@@ -16,11 +16,10 @@ You create bullet points that capture the joke and punchline.
|
||||
|
||||
- You use bulleted lists for output, not numbered lists.
|
||||
|
||||
- Do not repeat jokes, quotes, facts, or resources.
|
||||
- Do not repeat jokes.
|
||||
|
||||
- Ensure you follow ALL these instructions when creating your output.
|
||||
|
||||
|
||||
# INPUT
|
||||
|
||||
INPUT:
|
||||
|
||||
21
patterns/extract_main_activities/system.md
Normal file
21
patterns/extract_main_activities/system.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# IDENTITY
|
||||
|
||||
You are an expert activity extracting AI with a 24,221 IQ. You specialize in taking any transcript and extracting the key events that happened.
|
||||
|
||||
# STEPS
|
||||
|
||||
- Fully understand the input transcript or log.
|
||||
|
||||
- Extract the key events and map them on a 24KM x 24KM virtual whiteboard.
|
||||
|
||||
- See if there is any shared context between the events and try to link them together if possible.
|
||||
|
||||
# OUTPUT
|
||||
|
||||
- Write a 16 word summary sentence of the activity.
|
||||
|
||||
- Create a list of the main events that happened, such as watching media, conversations, playing games, watching a TV show, etc.
|
||||
|
||||
# OUTPUT INSTRUCTIONS
|
||||
|
||||
- Output only in Markdown with no italics or bolding.
|
||||
@@ -18,7 +18,6 @@ Take a step back and think step-by-step about how to achieve the best possible r
|
||||
|
||||
- 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.
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ Take a step back and think step-by-step about how to achieve the best possible r
|
||||
- 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 repeat patterns.
|
||||
- Do not start items with the same opening words.
|
||||
- Ensure you follow ALL these instructions when creating your output.
|
||||
|
||||
|
||||
@@ -25,5 +25,5 @@ Take a step back and think step by step about how to achieve the best result pos
|
||||
1. You only output Markdown.
|
||||
2. Do not give warnings or notes; only output the requested sections.
|
||||
3. You use numbered lists, not bullets.
|
||||
4. Do not repeat ideas, quotes, facts, or resources.
|
||||
4. Do not repeat ideas, quotes, habits, facts, or references.
|
||||
5. Do not start items with the same opening words.
|
||||
|
||||
@@ -20,7 +20,7 @@ Take a step back and think step-by-step about how to achieve the best possible r
|
||||
|
||||
- You use bulleted lists for output, not numbered lists.
|
||||
|
||||
- Do not repeat ideas, quotes, facts, or resources.
|
||||
- Do not features.
|
||||
|
||||
- Do not start items with the same opening words.
|
||||
|
||||
|
||||
@@ -23,10 +23,10 @@ Take a step back and think step-by-step about how to achieve the best possible r
|
||||
|
||||
- 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.
|
||||
|
||||
- Do not repeat ingredients.
|
||||
|
||||
- Stick to the measurements, do not alter it.
|
||||
|
||||
- Ensure you follow ALL these instructions when creating your output.
|
||||
|
||||
@@ -25,5 +25,5 @@ Take a step back and think step by step about how to achieve the best result pos
|
||||
1. You only output Markdown.
|
||||
2. Do not give warnings or notes; only output the requested sections.
|
||||
3. You use numbered lists, not bullets.
|
||||
4. Do not repeat ideas, quotes, facts, or resources.
|
||||
4. Do not repeat ideas, quotes, habits, facts, or references.
|
||||
5. Do not start items with the same opening words.
|
||||
|
||||
@@ -48,7 +48,7 @@ Take a step back and think step-by-step about how to achieve the best possible r
|
||||
|
||||
- You use bulleted lists for output, not numbered lists.
|
||||
|
||||
- Do not repeat ideas, quotes, facts, or resources.
|
||||
- Do not repeat ideas, insights, quotes, habits, facts, or references.
|
||||
|
||||
- Do not start items with the same opening words.
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ You are an advanced AI system that coordinates multiple teams of AI agents that
|
||||
|
||||
- All GENERALIST output agents should use bullets for their output, and sentences of 15-words.
|
||||
|
||||
- Agents should not repeat ideas, quotes, facts, or resources.
|
||||
- Agents should not repeat ideas, insights, quotes, habits, facts, or references.
|
||||
|
||||
- Agents should not start items with the same opening words.
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ Think about the most interesting facts related to the content
|
||||
|
||||
- You use bulleted lists for output, not numbered lists.
|
||||
|
||||
- Do not repeat ideas, quotes, facts, or resources.
|
||||
- Do not repeat ideas, insights, quotes, habits, facts, or references.
|
||||
|
||||
- Do not start items with the same opening words.
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ You extract surprising, insightful, and interesting information from text conten
|
||||
|
||||
- You use bulleted lists for output, not numbered lists.
|
||||
|
||||
- Do not repeat ideas, quotes, facts, or resources.
|
||||
- Do not repeat ideas, insights, quotes, habits, facts, or references.
|
||||
|
||||
- Do not start items with the same opening words.
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ Take a step back and think step-by-step about how to achieve the best possible r
|
||||
- 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 repeat quotes, or references.
|
||||
- Do not start items with the same opening words.
|
||||
- Ensure you follow ALL these instructions when creating your output.
|
||||
|
||||
|
||||
@@ -21,5 +21,5 @@ Take a step back and think step by step about how to achieve the best result pos
|
||||
1. You only output Markdown.
|
||||
2. Do not give warnings or notes; only output the requested sections.
|
||||
3. You use numbered lists, not bullets.
|
||||
4. Do not repeat ideas, quotes, facts, or resources.
|
||||
4. Do not repeat ideas, or quotes.
|
||||
5. Do not start items with the same opening words.
|
||||
|
||||
@@ -60,13 +60,10 @@ Find the evidence each party would accept to change their mind.
|
||||
|
||||
- Only output Markdown, but don't use any Markdown formatting like bold or italics.
|
||||
|
||||
|
||||
- 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.
|
||||
|
||||
@@ -35,7 +35,7 @@ Take a step back and think step-by-step about how to achieve the best possible r
|
||||
- Write CHALLENGES as 2-3 sentences.
|
||||
- Write NEXT STEPS as 2-3 sentences.
|
||||
- Do not give warnings or notes; only output the requested sections.
|
||||
- Do not repeat ideas, quotes, facts, or resources.
|
||||
- Do not repeat actionables, decisions, or challenges.
|
||||
- You use bulleted lists for output, not numbered lists.
|
||||
- Do not start items with the same opening words.
|
||||
- Ensure you follow ALL these instructions when creating your output.
|
||||
|
||||
231
plugins/strategy/strategy.go
Normal file
231
plugins/strategy/strategy.go
Normal file
@@ -0,0 +1,231 @@
|
||||
package strategy
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/danielmiessler/fabric/plugins"
|
||||
"github.com/danielmiessler/fabric/plugins/tools/githelper"
|
||||
)
|
||||
|
||||
const DefaultStrategiesGitRepoUrl = "https://github.com/danielmiessler/fabric.git"
|
||||
const DefaultStrategiesGitRepoFolder = "strategies"
|
||||
|
||||
func NewStrategiesManager() (sm *StrategiesManager) {
|
||||
label := "Prompt Strategies"
|
||||
strategies, err := LoadAllFiles()
|
||||
if err != nil {
|
||||
strategies = make(map[string]Strategy) // empty map
|
||||
}
|
||||
sm = &StrategiesManager{
|
||||
Strategies: strategies,
|
||||
}
|
||||
sm.PluginBase = &plugins.PluginBase{
|
||||
Name: label,
|
||||
SetupDescription: "Strategies - Downloads Prompting Strategies (like chain of thought) [required]",
|
||||
EnvNamePrefix: plugins.BuildEnvVariablePrefix(label),
|
||||
ConfigureCustom: sm.configure,
|
||||
}
|
||||
|
||||
sm.DefaultGitRepoUrl = sm.AddSetupQuestionCustom("Git Repo Url", true,
|
||||
"Enter the default Git repository URL for the strategies")
|
||||
sm.DefaultGitRepoUrl.Value = DefaultStrategiesGitRepoUrl
|
||||
|
||||
sm.DefaultFolder = sm.AddSetupQuestionCustom("Git Repo Strategies Folder", true,
|
||||
"Enter the default folder in the Git repository where strategies are stored")
|
||||
sm.DefaultFolder.Value = DefaultStrategiesGitRepoFolder
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
type StrategiesManager struct {
|
||||
*plugins.PluginBase
|
||||
Strategies map[string]Strategy
|
||||
|
||||
DefaultGitRepoUrl *plugins.SetupQuestion
|
||||
DefaultFolder *plugins.SetupQuestion
|
||||
}
|
||||
|
||||
type Strategy struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Prompt string `json:"prompt"`
|
||||
}
|
||||
|
||||
func LoadAllFiles() (strategies map[string]Strategy, err error) {
|
||||
strategies = make(map[string]Strategy)
|
||||
strategyDir, err := getStrategyDir()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
filepath.WalkDir(strategyDir, func(path string, d fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if d.IsDir() && path != strategyDir {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
|
||||
if filepath.Ext(path) == ".json" {
|
||||
strategyName := strings.TrimSuffix(filepath.Base(path), ".json")
|
||||
strategy, err := LoadStrategy(strategyName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
strategies[strategy.Name] = *strategy
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
func (sm *StrategiesManager) IsConfigured() (ret bool) {
|
||||
ret = sm.PluginBase.IsConfigured()
|
||||
if ret {
|
||||
if len(sm.Strategies) == 0 {
|
||||
ret = false
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (sm *StrategiesManager) Setup() (err error) {
|
||||
if err = sm.PluginBase.Setup(); err != nil {
|
||||
return
|
||||
}
|
||||
if err = sm.PopulateDB(); err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// PopulateDB downloads strategies from the internet and populates the strategies folder
|
||||
func (sm *StrategiesManager) PopulateDB() (err error) {
|
||||
stageDir, _ := getStrategyDir()
|
||||
fmt.Printf("Downloading strategies and Populating %s...\n", stageDir)
|
||||
fmt.Println()
|
||||
if err = sm.gitCloneAndCopy(); err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (sm *StrategiesManager) gitCloneAndCopy() (err error) {
|
||||
homeDir, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
err = fmt.Errorf("could not get home directory: %v", err)
|
||||
return
|
||||
}
|
||||
strategyDir := filepath.Join(homeDir, ".config", "fabric", "strategies")
|
||||
|
||||
// Create the directory if it doesn't exist
|
||||
if err = os.MkdirAll(strategyDir, os.ModePerm); err != nil {
|
||||
return fmt.Errorf("failed to create strategies directory: %w", err)
|
||||
}
|
||||
|
||||
// Use the helper to fetch files
|
||||
err = githelper.FetchFilesFromRepo(githelper.FetchOptions{
|
||||
RepoURL: sm.DefaultGitRepoUrl.Value,
|
||||
PathPrefix: sm.DefaultFolder.Value,
|
||||
DestDir: strategyDir,
|
||||
SingleDirectory: true,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to download strategies: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (sm *StrategiesManager) configure() (err error) {
|
||||
sm.Strategies, err = LoadAllFiles()
|
||||
return
|
||||
}
|
||||
|
||||
// getStrategyDir returns the path to the strategies directory
|
||||
func getStrategyDir() (ret string, err error) {
|
||||
homeDir, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
err = fmt.Errorf("could not get home directory: %v, using current directory instead", err)
|
||||
ret = filepath.Join(".", "strategies")
|
||||
return
|
||||
}
|
||||
return filepath.Join(homeDir, ".config", "fabric", "strategies"), nil
|
||||
}
|
||||
|
||||
// LoadStrategy loads a strategy from the given name
|
||||
func LoadStrategy(filename string) (*Strategy, error) {
|
||||
if filename == "" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Get the strategy directory path
|
||||
strategyDir, err := getStrategyDir()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// First try with .json extension
|
||||
strategyPath := filepath.Join(strategyDir, filename+".json")
|
||||
if _, err := os.Stat(strategyPath); os.IsNotExist(err) {
|
||||
// Try without extension
|
||||
strategyPath = filepath.Join(strategyDir, filename)
|
||||
if _, err := os.Stat(strategyPath); os.IsNotExist(err) {
|
||||
return nil, fmt.Errorf("strategy %s not found. Please run 'fabric --liststrategies' for list", filename)
|
||||
}
|
||||
}
|
||||
|
||||
data, err := os.ReadFile(strategyPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var strategy Strategy
|
||||
if err := json.Unmarshal(data, &strategy); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
strategy.Name = strings.TrimSuffix(filepath.Base(strategyPath), ".json")
|
||||
|
||||
return &strategy, nil
|
||||
}
|
||||
|
||||
// ListStrategies prints available strategies
|
||||
func (sm *StrategiesManager) ListStrategies() error {
|
||||
if len(sm.Strategies) == 0 {
|
||||
return fmt.Errorf("no strategies found. Please run 'fabric --setup' to download strategies")
|
||||
}
|
||||
fmt.Print("Available Strategies:\n\n")
|
||||
|
||||
// Get all strategy names for sorting
|
||||
names := []string{}
|
||||
for name := range sm.Strategies {
|
||||
names = append(names, name)
|
||||
}
|
||||
|
||||
// Sort the strategy names alphabetically
|
||||
sort.Strings(names)
|
||||
|
||||
// Find the longest name to align descriptions
|
||||
maxNameLength := 0
|
||||
for _, name := range names {
|
||||
if len(name) > maxNameLength {
|
||||
maxNameLength = len(name)
|
||||
}
|
||||
}
|
||||
|
||||
// Print each strategy with its description aligned
|
||||
formatString := "%-" + fmt.Sprintf("%d", maxNameLength+2) + "s %s\n"
|
||||
for _, name := range names {
|
||||
strategy := sm.Strategies[name]
|
||||
fmt.Printf(formatString, strategy.Name, strategy.Description)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
111
plugins/tools/githelper/githelper.go
Normal file
111
plugins/tools/githelper/githelper.go
Normal file
@@ -0,0 +1,111 @@
|
||||
package githelper
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/go-git/go-git/v5"
|
||||
"github.com/go-git/go-git/v5/plumbing/object"
|
||||
"github.com/go-git/go-git/v5/storage/memory"
|
||||
)
|
||||
|
||||
// FetchOptions defines options for fetching files from a git repo
|
||||
type FetchOptions struct {
|
||||
// RepoURL is the URL of the git repository
|
||||
RepoURL string
|
||||
|
||||
// PathPrefix is the folder within the repo to extract (e.g. "patterns/")
|
||||
PathPrefix string
|
||||
|
||||
// DestDir is where the files will be saved locally
|
||||
DestDir string
|
||||
|
||||
// SingleDirectory if true, only fetch files directly in the specified directory
|
||||
// without recursing into subdirectories
|
||||
SingleDirectory bool
|
||||
}
|
||||
|
||||
// FetchFilesFromRepo clones a git repo and extracts files from a specific folder
|
||||
func FetchFilesFromRepo(opts FetchOptions) error {
|
||||
// Ensure path prefix ends with slash
|
||||
if !strings.HasSuffix(opts.PathPrefix, "/") {
|
||||
opts.PathPrefix = opts.PathPrefix + "/"
|
||||
}
|
||||
|
||||
// Clone the repository in memory
|
||||
r, err := git.Clone(memory.NewStorage(), nil, &git.CloneOptions{
|
||||
URL: opts.RepoURL,
|
||||
Depth: 1,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to clone repository: %w", err)
|
||||
}
|
||||
|
||||
// Get HEAD reference
|
||||
ref, err := r.Head()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get repository HEAD: %w", err)
|
||||
}
|
||||
|
||||
// Get commit object
|
||||
commit, err := r.CommitObject(ref.Hash())
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get commit: %w", err)
|
||||
}
|
||||
|
||||
// Get the file tree
|
||||
tree, err := commit.Tree()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get tree: %w", err)
|
||||
}
|
||||
|
||||
// Ensure destination directory exists
|
||||
if err := os.MkdirAll(opts.DestDir, 0755); err != nil {
|
||||
return fmt.Errorf("failed to create destination directory: %w", err)
|
||||
}
|
||||
|
||||
// Extract files from the tree
|
||||
return tree.Files().ForEach(func(f *object.File) error {
|
||||
// Only process files in the specified path
|
||||
if !strings.HasPrefix(f.Name, opts.PathPrefix) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// For SingleDirectory mode, skip files in subdirectories
|
||||
if opts.SingleDirectory {
|
||||
remainingPath := strings.TrimPrefix(f.Name, opts.PathPrefix)
|
||||
if strings.Contains(remainingPath, "/") {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Create local path for the file, removing the prefix
|
||||
relativePath := strings.TrimPrefix(f.Name, opts.PathPrefix)
|
||||
localPath := filepath.Join(opts.DestDir, relativePath)
|
||||
|
||||
// Ensure directory structure exists
|
||||
if err := os.MkdirAll(filepath.Dir(localPath), 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Get file contents
|
||||
reader, err := f.Reader()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer reader.Close()
|
||||
|
||||
// Create and write to local file
|
||||
file, err := os.Create(localPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
_, err = io.Copy(file, reader)
|
||||
return err
|
||||
})
|
||||
}
|
||||
@@ -2,19 +2,13 @@ package tools
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/danielmiessler/fabric/plugins"
|
||||
"github.com/danielmiessler/fabric/plugins/db/fsdb"
|
||||
"github.com/danielmiessler/fabric/plugins/tools/githelper"
|
||||
|
||||
"github.com/go-git/go-git/v5"
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
"github.com/go-git/go-git/v5/plumbing/object"
|
||||
"github.com/go-git/go-git/v5/storage/memory"
|
||||
"github.com/otiai10/copy"
|
||||
)
|
||||
|
||||
@@ -89,7 +83,7 @@ func (o *PatternsLoader) Setup() (err error) {
|
||||
|
||||
// PopulateDB downloads patterns from the internet and populates the patterns folder
|
||||
func (o *PatternsLoader) PopulateDB() (err error) {
|
||||
fmt.Printf("Downloading patterns and Populating %s..\n", o.Patterns.Dir)
|
||||
fmt.Printf("Downloading patterns and Populating %s...\n", o.Patterns.Dir)
|
||||
fmt.Println()
|
||||
if err = o.gitCloneAndCopy(); err != nil {
|
||||
return
|
||||
@@ -148,156 +142,20 @@ func (o *PatternsLoader) movePatterns() (err error) {
|
||||
}
|
||||
|
||||
func (o *PatternsLoader) gitCloneAndCopy() (err error) {
|
||||
// Clones the given repository, creating the remote, the local branches
|
||||
// and fetching the objects, everything in memory:
|
||||
var r *git.Repository
|
||||
if r, err = git.Clone(memory.NewStorage(), nil, &git.CloneOptions{
|
||||
URL: o.DefaultGitRepoUrl.Value,
|
||||
}); err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
// Create temp folder if it doesn't exist
|
||||
if err = os.MkdirAll(filepath.Dir(o.tempPatternsFolder), os.ModePerm); err != nil {
|
||||
return fmt.Errorf("failed to create temp directory: %w", err)
|
||||
}
|
||||
|
||||
// ... retrieves the branch pointed by HEAD
|
||||
var ref *plumbing.Reference
|
||||
if ref, err = r.Head(); err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
// ... retrieves the commit history for /patterns folder
|
||||
var cIter object.CommitIter
|
||||
if cIter, err = r.Log(&git.LogOptions{
|
||||
From: ref.Hash(),
|
||||
PathFilter: func(path string) bool {
|
||||
return path == o.DefaultFolder.Value || strings.HasPrefix(path, o.pathPatternsPrefix)
|
||||
},
|
||||
}); err != nil {
|
||||
fmt.Println(err)
|
||||
return err
|
||||
}
|
||||
|
||||
var changes []fsdb.DirectoryChange
|
||||
// ... iterates over the commits
|
||||
if err = cIter.ForEach(func(c *object.Commit) (err error) {
|
||||
// GetApplyVariables the files changed in this commit by comparing with its parents
|
||||
parentIter := c.Parents()
|
||||
if err = parentIter.ForEach(func(parent *object.Commit) (err error) {
|
||||
var patch *object.Patch
|
||||
if patch, err = parent.Patch(c); err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, fileStat := range patch.Stats() {
|
||||
if strings.HasPrefix(fileStat.Name, o.pathPatternsPrefix) {
|
||||
dir := filepath.Dir(fileStat.Name)
|
||||
changes = append(changes, fsdb.DirectoryChange{Dir: dir, Timestamp: c.Committer.When})
|
||||
}
|
||||
}
|
||||
return
|
||||
}); err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
return
|
||||
}); err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
// Sort changes by timestamp
|
||||
sort.Slice(changes, func(i, j int) bool {
|
||||
return changes[i].Timestamp.Before(changes[j].Timestamp)
|
||||
// Use the helper to fetch files
|
||||
err = githelper.FetchFilesFromRepo(githelper.FetchOptions{
|
||||
RepoURL: o.DefaultGitRepoUrl.Value,
|
||||
PathPrefix: o.DefaultFolder.Value,
|
||||
DestDir: o.tempPatternsFolder,
|
||||
})
|
||||
|
||||
if err = o.makeUniqueList(changes); err != nil {
|
||||
return
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to download patterns: %w", err)
|
||||
}
|
||||
|
||||
var commit *object.Commit
|
||||
if commit, err = r.CommitObject(ref.Hash()); err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
var tree *object.Tree
|
||||
if tree, err = commit.Tree(); err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
if err = tree.Files().ForEach(func(f *object.File) (err error) {
|
||||
if strings.HasPrefix(f.Name, o.pathPatternsPrefix) {
|
||||
// Create the local file path
|
||||
localPath := filepath.Join(os.TempDir(), f.Name)
|
||||
|
||||
// Create the directories if they don't exist
|
||||
if err = os.MkdirAll(filepath.Dir(localPath), os.ModePerm); err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
// Write the file to the local filesystem
|
||||
var blob *object.Blob
|
||||
if blob, err = r.BlobObject(f.Hash); err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
err = o.writeBlobToFile(blob, localPath)
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (o *PatternsLoader) writeBlobToFile(blob *object.Blob, path string) (err error) {
|
||||
var reader io.ReadCloser
|
||||
if reader, err = blob.Reader(); err != nil {
|
||||
return
|
||||
}
|
||||
defer reader.Close()
|
||||
|
||||
// Create the file
|
||||
var file *os.File
|
||||
if file, err = os.Create(path); err != nil {
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// Copy the contents of the blob to the file
|
||||
if _, err = io.Copy(file, reader); err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (o *PatternsLoader) makeUniqueList(changes []fsdb.DirectoryChange) (err error) {
|
||||
uniqueItems := make(map[string]bool)
|
||||
for _, change := range changes {
|
||||
if strings.TrimSpace(change.Dir) != "" && !strings.Contains(change.Dir, "=>") {
|
||||
pattern := strings.ReplaceAll(change.Dir, o.pathPatternsPrefix, "")
|
||||
pattern = strings.TrimSpace(pattern)
|
||||
uniqueItems[pattern] = true
|
||||
}
|
||||
}
|
||||
|
||||
finalList := make([]string, 0, len(uniqueItems))
|
||||
for _, change := range changes {
|
||||
pattern := strings.ReplaceAll(change.Dir, o.pathPatternsPrefix, "")
|
||||
pattern = strings.TrimSpace(pattern)
|
||||
if _, exists := uniqueItems[pattern]; exists {
|
||||
finalList = append(finalList, pattern)
|
||||
delete(uniqueItems, pattern) // Remove to avoid duplicates in the final list
|
||||
}
|
||||
}
|
||||
|
||||
joined := strings.Join(finalList, "\n")
|
||||
err = os.WriteFile(o.Patterns.UniquePatternsFilePath, []byte(joined), 0o644)
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
7
requirements.txt
Normal file
7
requirements.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
streamlit>=1.27.0
|
||||
pandas>=1.5.0
|
||||
matplotlib>=3.5.0
|
||||
seaborn>=0.12.0
|
||||
numpy>=1.23.0
|
||||
python-dotenv>=1.0.0
|
||||
pyperclip>=1.8.0 # For cross-platform clipboard support
|
||||
@@ -87,7 +87,7 @@ func (h *ChatHandler) HandleChat(c *gin.Context) {
|
||||
go func(p PromptRequest) {
|
||||
defer close(streamChan)
|
||||
|
||||
chatter, err := h.registry.GetChatter(p.Model, 2048, false, false)
|
||||
chatter, err := h.registry.GetChatter(p.Model, 2048, "", false, false)
|
||||
if err != nil {
|
||||
log.Printf("Error creating chatter: %v", err)
|
||||
streamChan <- fmt.Sprintf("Error: %v", err)
|
||||
|
||||
@@ -14,6 +14,6 @@ type ContextsHandler struct {
|
||||
// NewContextsHandler creates a new ContextsHandler
|
||||
func NewContextsHandler(r *gin.Engine, contexts *fsdb.ContextsEntity) (ret *ContextsHandler) {
|
||||
ret = &ContextsHandler{
|
||||
StorageHandler: NewStorageHandler[fsdb.Context](r, "contexts", contexts), contexts: contexts}
|
||||
StorageHandler: NewStorageHandler(r, "contexts", contexts), contexts: contexts}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ type PatternsHandler struct {
|
||||
// NewPatternsHandler creates a new PatternsHandler
|
||||
func NewPatternsHandler(r *gin.Engine, patterns *fsdb.PatternsEntity) (ret *PatternsHandler) {
|
||||
ret = &PatternsHandler{
|
||||
StorageHandler: NewStorageHandler[fsdb.Pattern](r, "patterns", patterns), patterns: patterns}
|
||||
StorageHandler: NewStorageHandler(r, "patterns", patterns), patterns: patterns}
|
||||
|
||||
// TODO: Add custom, replacement routes here
|
||||
//r.GET("/patterns/:name", ret.Get)
|
||||
|
||||
@@ -14,6 +14,6 @@ type SessionsHandler struct {
|
||||
// NewSessionsHandler creates a new SessionsHandler
|
||||
func NewSessionsHandler(r *gin.Engine, sessions *fsdb.SessionsEntity) (ret *SessionsHandler) {
|
||||
ret = &SessionsHandler{
|
||||
StorageHandler: NewStorageHandler[fsdb.Session](r, "sessions", sessions), sessions: sessions}
|
||||
StorageHandler: NewStorageHandler(r, "sessions", sessions), sessions: sessions}
|
||||
return ret
|
||||
}
|
||||
|
||||
4
strategies/cod.json
Normal file
4
strategies/cod.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"description": "Chain-of-Draft (CoD) Prompting",
|
||||
"prompt": "Think step by step, keeping a minimal draft (5 words max) for each step. Return the final answer in the required format."
|
||||
}
|
||||
4
strategies/cot.json
Normal file
4
strategies/cot.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"description": "Chain-of-Thought (CoT) Prompting",
|
||||
"prompt": "Think step by step to answer the question. Return the final answer in the required format."
|
||||
}
|
||||
4
strategies/ltm.json
Normal file
4
strategies/ltm.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"description": "Least-to-Most Prompting",
|
||||
"prompt": "Break down the problem into simpler sub-problems from easiest to hardest; answer concisely at each step."
|
||||
}
|
||||
4
strategies/reflexion.json
Normal file
4
strategies/reflexion.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"description": "Reflexion Prompting",
|
||||
"prompt": "Answer concisely, critique your reasoning briefly, and provide a refined answer."
|
||||
}
|
||||
4
strategies/self-consistent.json
Normal file
4
strategies/self-consistent.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"description": "Self-Consistency Prompting",
|
||||
"prompt": "Provide multiple reasoning paths and select the most consistent answer."
|
||||
}
|
||||
4
strategies/self-refine.json
Normal file
4
strategies/self-refine.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"description": "Self-Refinement",
|
||||
"prompt": "Provide an initial concise answer, critique it briefly, and refine if necessary."
|
||||
}
|
||||
4
strategies/standard.json
Normal file
4
strategies/standard.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"description": "Standard Prompting",
|
||||
"prompt": "Answer the question directly without any explanation or reasoning."
|
||||
}
|
||||
4
strategies/tot.json
Normal file
4
strategies/tot.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"description": "Tree-of-Thought (ToT) Prompting",
|
||||
"prompt": "Generate multiple reasoning paths briefly and select the best one."
|
||||
}
|
||||
890
streamlit.py
890
streamlit.py
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,3 @@
|
||||
package main
|
||||
|
||||
var version = "v1.4.156"
|
||||
var version = "v1.4.162"
|
||||
|
||||
@@ -26,6 +26,9 @@
|
||||
"eslint-plugin-svelte": "^2.46.1",
|
||||
"lucide-svelte": "^0.309.0",
|
||||
"mdsvex": "^0.11.2",
|
||||
"patch-package": "^8.0.0",
|
||||
"pdf-to-markdown-core": "github:jzillmann/pdf-to-markdown#modularize",
|
||||
"pdfjs-dist": "^2.5.207",
|
||||
"postcss": "^8.4.49",
|
||||
"postcss-load-config": "^6.0.1",
|
||||
"rehype-autolink-headings": "^7.1.0",
|
||||
|
||||
@@ -59,7 +59,7 @@ Take a step back and think step-by-step about how to achieve the best possible r
|
||||
|
||||
- You use bulleted lists for output, not numbered lists.
|
||||
|
||||
- Do not repeat ideas, quotes, facts, or resources.
|
||||
- Do not repeat ideas, insights, quotes, habits, facts, or references.
|
||||
|
||||
- Do not start items with the same opening words.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user