Compare commits

...

27 Commits

Author SHA1 Message Date
github-actions[bot]
7eed80710e Update version to v1.4.162 and commit 2025-03-19 03:45:25 +00:00
Eugen Eisler
fbd62be47d Merge pull request #1374 from ksylvan/fix/change-default-model-save
Fix Default Model Change Functionality
2025-03-19 04:44:11 +01:00
Kayvan Sylvan
85cc7b8a9d fix: improve error handling in ChangeDefaultModel flow and save environment file
- Add early return on setup error
- Save environment file after successful setup
- Maintain proper error propagation
2025-03-17 19:37:26 -07:00
github-actions[bot]
0eee89140c Update version to v1.4.161 and commit 2025-03-17 14:21:02 +00:00
Eugen Eisler
5571e6fafd Merge pull request #1363 from garkpit/streamlit-clipboard-ops-for-all-platforms
clipboard operations now work on Mac and PC
2025-03-17 15:19:42 +01:00
github-actions[bot]
9a4e920618 Update version to v1.4.160 and commit 2025-03-17 14:17:36 +00:00
Eugen Eisler
6e479999b1 Merge pull request #1368 from vaygr/std-no-repeat
Standardize sections for no repeat guidelines
2025-03-17 15:16:21 +01:00
Daniel Miessler
f65f2501b4 Moved system file to proper directory. 2025-03-16 14:46:13 -07:00
Daniel Miessler
4b12bd2a61 Moved system file to proper directory. 2025-03-16 14:43:55 -07:00
Daniel Miessler
d83a3beeeb Merge branch 'main' of github.com:danielmiessler/fabric 2025-03-16 14:16:02 -07:00
Daniel Miessler
7428c8017f Added activity extractor. 2025-03-16 14:15:54 -07:00
Val V
008ed76d37 Standardize sections for no repeat guidelines 2025-03-16 19:48:15 +00:00
github-actions[bot]
ce9d4ad831 Update version to v1.4.159 and commit 2025-03-16 19:23:15 +00:00
Daniel Miessler
657bcab48c Added flashcard generator. 2025-03-16 12:21:50 -07:00
github-actions[bot]
cd11dcc7a9 Update version to v1.4.158 and commit 2025-03-16 17:26:52 +00:00
Eugen Eisler
22040a42f2 Merge pull request #1367 from ksylvan/fix/code_cleanup
Remove Generic Type Parameters from StorageHandler Initialization
2025-03-16 18:25:33 +01:00
Kayvan Sylvan
705ccd750b refactor: remove generic type parameters from NewStorageHandler calls
## CHANGES

- Remove explicit type parameters from StorageHandler initialization
- Update contexts handler constructor implementation
- Update patterns handler constructor implementation
- Update sessions handler constructor implementation
- Simplify API by relying on type inference
2025-03-16 09:21:17 -07:00
github-actions[bot]
db7c2b70cb Update version to v1.4.157 and commit 2025-03-16 07:36:39 +00:00
Eugen Eisler
9dc9bfa1d5 Merge pull request #1365 from ksylvan/feature/strategies
Implement Prompt Strategies in Fabric
2025-03-16 08:35:23 +01:00
Kayvan Sylvan
6b93658191 chore: remove redundant yt function definition 2025-03-15 17:35:45 -07:00
Kayvan Sylvan
ea7a425a26 add newline to end of cod.json 2025-03-15 13:18:53 -07:00
Kayvan Sylvan
9582978adb Fix help message when no strategies found. 2025-03-15 13:05:51 -07:00
Kayvan Sylvan
453d8e75e4 fix: fix handling of the installed strategies dir 2025-03-15 09:36:34 -07:00
Kayvan Sylvan
901a010efd chore: remove fallback to local strategies directory if missing 2025-03-15 08:29:58 -07:00
Jay
b5c2d069f2 clipboard operations now work on Mac and PC 2025-03-15 08:31:48 +00:00
Kayvan Sylvan
f744e25b39 change [optional] to [required] in strategies 2025-03-15 00:33:58 -07:00
Kayvan Sylvan
096f40df68 feat: add prompt strategies and improve installation documentation
## CHANGES

- Add prompt strategies like Chain of Thought (CoT)
- Implement strategy selection with `--strategy` flag
- Improve README with platform-specific installation instructions
- Fix web interface documentation link
- Refactor git operations with new githelper package
- Add `--liststrategies` command to view available strategies
- Support applying strategies to system prompts
- Fix YouTube configuration check
- Improve error handling in session management
2025-03-15 00:30:30 -07:00
56 changed files with 1167 additions and 581 deletions

View File

@@ -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
View File

@@ -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]

View File

@@ -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
}

View File

@@ -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,

View File

@@ -13,6 +13,7 @@ type ChatRequest struct {
Language string
Meta string
InputHasVars bool
StrategyName string
}
type ChatOptions struct {

View File

@@ -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)
}

View File

@@ -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
}

View File

@@ -1 +1 @@
"1.4.156"
"1.4.162"

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View 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).

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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:

View File

@@ -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.

View File

@@ -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.

View File

@@ -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:

View 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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View 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
}

View 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
})
}

View File

@@ -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
View 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

View File

@@ -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)

View File

@@ -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
}

View File

@@ -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)

View File

@@ -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
View 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
View 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
View 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."
}

View File

@@ -0,0 +1,4 @@
{
"description": "Reflexion Prompting",
"prompt": "Answer concisely, critique your reasoning briefly, and provide a refined answer."
}

View File

@@ -0,0 +1,4 @@
{
"description": "Self-Consistency Prompting",
"prompt": "Provide multiple reasoning paths and select the most consistent answer."
}

View 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
View File

@@ -0,0 +1,4 @@
{
"description": "Standard Prompting",
"prompt": "Answer the question directly without any explanation or reasoning."
}

4
strategies/tot.json Normal file
View File

@@ -0,0 +1,4 @@
{
"description": "Tree-of-Thought (ToT) Prompting",
"prompt": "Generate multiple reasoning paths briefly and select the best one."
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +1,3 @@
package main
var version = "v1.4.156"
var version = "v1.4.162"

View File

@@ -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",

View File

@@ -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.