Compare commits

..

19 Commits

Author SHA1 Message Date
github-actions[bot]
43ca0dccf7 Update version to v1.4.118 and commit 2024-12-05 09:34:13 +00:00
Eugen Eisler
fcfcf55610 Merge pull request #1174 from mattjoyce/curly-brace-templates
Curly brace templates
2024-12-05 10:33:16 +01:00
Eugen Eisler
188235efc5 Merge pull request #1179 from sluosapher/main
added a new pattern create_newsletter_entry
2024-12-05 10:32:23 +01:00
Song Luo
fdd1d614b2 added a new pattern create_newsletter_entry 2024-12-03 20:05:25 -05:00
Matt Joyce
fc67dea243 fixed : if there is no stdin, then a nil message was passed to pattern.go resulting in segfault.
now we make user input ' ', before processing.
2024-12-03 13:33:45 +11:00
Matt Joyce
efd363d5fb Revert "Fix pattern file usage without stdin"
This reverts commit 744ec0824b.
2024-12-03 13:33:45 +11:00
Matt Joyce
a7d6de1661 Fix pattern file usage without stdin
When using pattern files with variables but no stdin input, ensure proper
template processing by initializing an empty message. This allows patterns
like:
  ./fabric -p pattern.txt -v=name:value

to work without requiring stdin input, while maintaining compatibility
with existing stdin usage:
  echo "input" | ./fabric -p pattern.txt -v=name:value

Changes:
- Add empty message initialization in BuildSession when Message is nil
- Remove redundant template processing of message content
- Let pattern processing handle all template resolution

This simplifies the template processing flow while supporting both
stdin and non-stdin use cases.
2024-12-03 13:33:40 +11:00
github-actions[bot]
c0ade48648 Update version to v1.4.117 and commit 2024-11-30 19:45:48 +00:00
Eugen Eisler
7fd4fa4742 fix: close #1173 2024-11-30 20:44:31 +01:00
github-actions[bot]
41b2e66c5c Update version to v1.4.116 and commit 2024-11-28 18:34:53 +00:00
Eugen Eisler
ed657383fb chore: cleanup style 2024-11-28 19:34:07 +01:00
github-actions[bot]
4d5d8d8b30 Update version to v1.4.115 and commit 2024-11-28 17:39:30 +00:00
Eugen Eisler
e9a75528ab chore: cleanup style 2024-11-28 18:36:01 +01:00
Eugen Eisler
c5ec4b548a fix: use the custom message and then piped one 2024-11-27 14:10:19 +01:00
Eugen Eisler
8e87529638 fix: use the custom message and then piped one 2024-11-27 14:10:18 +01:00
xssdoctor
ca33208fa1 Merge pull request #1168 from johnconnor-sec/main 2024-11-26 19:19:45 -05:00
John Connor
3f8bca8728 Update README.md 2024-11-26 19:15:18 -05:00
John Connor
ba56c33cf6 Update README.md 2024-11-26 19:12:29 -05:00
Jonathan Dunn
6ee4fdd366 updated readme 2024-11-26 17:53:58 -05:00
11 changed files with 127 additions and 72 deletions

View File

@@ -26,6 +26,7 @@
[Meta](#meta)
![Screenshot of fabric](images/fabric-summarize.png)
</div>
## Navigation
@@ -56,6 +57,7 @@
- [`to_pdf`](#to_pdf)
- [`to_pdf` Installation](#to_pdf-installation)
- [pbpaste](#pbpaste)
- [Web Interface](#Web_Interface)
- [Meta](#meta)
- [Primary contributors](#primary-contributors)
@@ -64,9 +66,9 @@
## Updates
> [!NOTE]
November 8, 2024
> * **Multimodal Support**: You can now us `-a` (attachment) for Multimodal submissions to OpenAI models that support it. Example: `fabric -a https://path/to/image "Give me a description of this image."`
> November 8, 2024
>
> - **Multimodal Support**: You can now us `-a` (attachment) for Multimodal submissions to OpenAI models that support it. Example: `fabric -a https://path/to/image "Give me a description of this image."`
## What and why
@@ -82,10 +84,10 @@ Fabric was created to address this by enabling everyone to granularly apply AI t
Keep in mind that many of these were recorded when Fabric was Python-based, so remember to use the current [install instructions](#Installation) below.
* [Network Chuck](https://www.youtube.com/watch?v=UbDyjIIGaxQ)
* [David Bombal](https://www.youtube.com/watch?v=vF-MQmVxnCs)
* [My Own Intro to the Tool](https://www.youtube.com/watch?v=wPEyyigh10g)
* [More Fabric YouTube Videos](https://www.youtube.com/results?search_query=fabric+ai)
- [Network Chuck](https://www.youtube.com/watch?v=UbDyjIIGaxQ)
- [David Bombal](https://www.youtube.com/watch?v=vF-MQmVxnCs)
- [My Own Intro to the Tool](https://www.youtube.com/watch?v=wPEyyigh10g)
- [More Fabric YouTube Videos](https://www.youtube.com/results?search_query=fabric+ai)
## Philosophy
@@ -155,6 +157,7 @@ go install github.com/danielmiessler/fabric@latest
You may need to set some environment variables in your `~/.bashrc` on linux or `~/.zshrc` file on mac to be able to run the `fabric` command. Here is an example of what you can add:
For Intel based macs or linux
```bash
# Golang environment variables
export GOROOT=/usr/local/go
@@ -165,6 +168,7 @@ export PATH=$GOPATH/bin:$GOROOT/bin:$HOME/.local/bin:$PATH
```
for Apple Silicon based macs
```bash
# Golang environment variables
export GOROOT=$(brew --prefix go)/libexec
@@ -173,14 +177,18 @@ export PATH=$GOPATH/bin:$GOROOT/bin:$HOME/.local/bin:$PATH
```
### Setup
Now run the following command
```bash
# Run the setup to set up your directories and keys
fabric --setup
```
If everything works you are good to go.
### Add aliases for all patterns
In order to add aliases for all your patterns and use them directly as commands ie. `summarize` instead of `fabric --pattern summarize`
You can add the following to your `.zshrc` or `.bashrc` file.
@@ -189,10 +197,10 @@ You can add the following to your `.zshrc` or `.bashrc` file.
for pattern_file in $HOME/.config/fabric/patterns/*; do
# Get the base name of the file (i.e., remove the directory path)
pattern_name=$(basename "$pattern_file")
# Create an alias in the form: alias pattern_name="fabric --pattern pattern_name"
alias_command="alias $pattern_name='fabric --pattern $pattern_name'"
# Evaluate the alias command to add it to the current shell
eval "$alias_command"
done
@@ -202,9 +210,11 @@ yt() {
fabric -y "$video_link" --transcript
}
```
This also creates a `yt` alias that allows you to use `yt https://www.youtube.com/watch?v=4b0iet22VIk` to get your transcripts.
#### Save your files in markdown using aliases
If in addition to the above aliases you would like to have the option to save the output to your favourite markdown note vault like Obsidian then instead of the above add the following to your `.zshrc` or `.bashrc` file:
```bash
@@ -244,7 +254,7 @@ yt() {
}
```
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.
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.
You can tweak the date format by tweaking the `date_stamp` format.
### Migration
@@ -268,11 +278,13 @@ Then [set your environmental variables](#environmental-variables) as shown above
### Upgrading
The great thing about Go is that it's super easy to upgrade. Just run the same command you used to install it in the first place and you'll always get the latest version.
```bash
go install github.com/danielmiessler/fabric@latest
```
## Usage
Once you have it all set up, here's how to use it.
```bash
@@ -320,6 +332,7 @@ Application Options:
--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
@@ -401,7 +414,6 @@ When you're ready to use them, copy them into:
You can then use them like any other Patterns, but they won't be public unless you explicitly submit them as Pull Requests to the Fabric project. So don't worry—they're private to you.
This feature works with all openai and ollama models but does NOT work with claude. You can specify your model with the -m flag
## Helper Apps
@@ -459,6 +471,29 @@ You can also create an alias by editing `~/.bashrc` or `~/.zshrc` and adding the
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.
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. 
_You will need to run fabric in a separate terminal with the `fabric --serve` command._
**From the fabric project `web/` directory:**
```shell
npm run dev
## or ##
pnpm run dev
## or your equivalent
```
## Meta
> [!NOTE]
@@ -467,6 +502,7 @@ alias pbpaste='xclip -selection clipboard -o'
- _Jonathan Dunn_ for being the absolute MVP dev on the project, including spearheading the new Go version, as well as the GUI! All this while also being a full-time medical doctor!
- _Caleb Sima_ for pushing me over the edge of whether to make this a public project or not.
- _Eugen Eisler_ and _Frederick Ros_ for their invaluable contributions to the Go version
- _David Peters_ for his work on the web interface.
- _Joel Parish_ for super useful input on the project's Github directory structure..
- _Joseph Thacker_ for the idea of a `-c` context flag that adds pre-created context in the `./config/fabric/` directory to all Pattern queries.
- _Jason Haddix_ for the idea of a stitch (chained Pattern) to filter content using a local model before sending on to a cloud model, i.e., cleaning customer data using `llama2` before sending on to `gpt-4` for analysis.

View File

@@ -63,8 +63,6 @@ type Flags struct {
// Init Initialize flags. returns a Flags struct and an error
func Init() (ret *Flags, err error) {
var message string
ret = &Flags{}
parser := flags.NewParser(ret, flags.Default)
var args []string
@@ -75,21 +73,19 @@ func Init() (ret *Flags, err error) {
info, _ := os.Stdin.Stat()
pipedToStdin := (info.Mode() & os.ModeCharDevice) == 0
//custom message
if len(args) > 0 {
ret.Message = AppendMessage(ret.Message, args[len(args)-1])
}
// takes input from stdin if it exists, otherwise takes input from args (the last argument)
if pipedToStdin {
//fmt.Printf("piped: %v\n", args)
if message, err = readStdin(); err != nil {
var pipedMessage string
if pipedMessage, err = readStdin(); err != nil {
return
}
} else if len(args) > 0 {
//fmt.Printf("no piped: %v\n", args)
message = args[len(args)-1]
} else {
//fmt.Printf("no data: %v\n", args)
message = ""
ret.Message = AppendMessage(ret.Message, pipedMessage)
}
ret.Message = message
return
}

View File

@@ -31,6 +31,15 @@ func (o *Chatter) Send(request *common.ChatRequest, opts *common.ChatOptions) (s
return
}
vendorMessages := session.GetVendorMessages()
if len(vendorMessages) == 0 {
if session.Name != "" {
err = o.db.Sessions.SaveSession(session)
}
err = fmt.Errorf("no messages provided")
return
}
if opts.Model == "" {
opts.Model = o.model
}
@@ -101,22 +110,27 @@ func (o *Chatter) BuildSession(request *common.ChatRequest, raw bool) (session *
contextContent = ctx.Content
}
var messageContent string
// Process any template variables in the message content (user input)
// Double curly braces {{variable}} indicate template substitution
// should occur, whether in patterns or direct input
if request.Message != nil {
request.Message.Content, err = template.ApplyTemplate(request.Message.Content, request.PatternVariables, "")
if err != nil {
return nil, err
// Ensure we have a message before processing, other wise we'll get an error when we pass to pattern.go
if request.Message == nil {
request.Message = &goopenai.ChatCompletionMessage{
Role: goopenai.ChatMessageRoleUser,
Content: " ",
}
messageContent = request.Message.Content
}
// Now we know request.Message is not nil, process template variables
request.Message.Content, err = template.ApplyTemplate(request.Message.Content, request.PatternVariables, "")
if err != nil {
return nil, err
}
var patternContent string
if request.PatternName != "" {
pattern, err := o.db.Patterns.GetApplyVariables(request.PatternName, request.PatternVariables, messageContent)
pattern, err := o.db.Patterns.GetApplyVariables(request.PatternName, request.PatternVariables, request.Message.Content)
// pattrn will now contain user input, and all variables will be resolved, or errored
if err != nil {
return nil, fmt.Errorf("could not get pattern %s: %v", request.PatternName, err)
}

View File

@@ -0,0 +1,20 @@
# Identity and Purpose
You are a custom GPT designed to create newsletter sections in the style of Frontend Weekly.
# Step-by-Step Process:
1. The user will provide article text.
2. Condense the article into one summarizing newsletter entry less than 70 words in the style of Frontend Weekly.
3. Generate a concise title for the entry, focus on the main idea or most important fact of the article
# Tone and Style Guidelines:
* Third-Party Narration: The newsletter should sound like its being narrated by an outside observer, someone who is both knowledgeable, unbiased and calm. Focus on the facts or main opinions in the original article. Creates a sense of objectivity and adds a layer of professionalism.
* Concise: Maintain brevity and clarity. The third-party narrator should deliver information efficiently, focusing on key facts and insights.
# Output Instructions:
Your final output should be a polished, newsletter-ready paragraph with a title line in bold followed by the summary paragraph.
# INPUT:
INPUT:

View File

View File

@@ -1 +1 @@
"1.4.114"
"1.4.118"

View File

@@ -22,10 +22,9 @@ type Pattern struct {
Pattern string
}
// main entry point for getting patterns from any source
func (o *PatternsEntity) GetApplyVariables(source string, variables map[string]string, input string) (*Pattern, error) {
var pattern *Pattern
var err error
// GetApplyVariables main entry point for getting patterns from any source
func (o *PatternsEntity) GetApplyVariables(
source string, variables map[string]string, input string) (pattern *Pattern, err error) {
// Determine if this is a file path
isFilePath := strings.HasPrefix(source, "\\") ||
@@ -40,17 +39,16 @@ func (o *PatternsEntity) GetApplyVariables(source string, variables map[string]s
}
if err != nil {
return nil, err
return
}
pattern, err = o.applyVariables(pattern, variables, input)
if err != nil {
return nil, err // Return the error if applyVariables failed
}
return pattern, nil
err = o.applyVariables(pattern, variables, input)
return
}
func (o *PatternsEntity) applyVariables(pattern *Pattern, variables map[string]string, input string) (*Pattern, error) {
func (o *PatternsEntity) applyVariables(
pattern *Pattern, variables map[string]string, input string) (err error) {
// If {{input}} isn't in pattern, append it on new line
if !strings.Contains(pattern.Pattern, "{{input}}") {
if !strings.HasSuffix(pattern.Pattern, "\n") {
@@ -59,12 +57,12 @@ func (o *PatternsEntity) applyVariables(pattern *Pattern, variables map[string]s
pattern.Pattern += "{{input}}"
}
result, err := template.ApplyTemplate(pattern.Pattern, variables, input)
if err != nil {
return nil, err
var result string
if result, err = template.ApplyTemplate(pattern.Pattern, variables, input); err != nil {
return
}
pattern.Pattern = result
return pattern, nil
return
}
// retrieves a pattern from the database by name
@@ -102,25 +100,27 @@ func (o *PatternsEntity) PrintLatestPatterns(latestNumber int) (err error) {
}
// reads a pattern from a file path and returns it
func (o *PatternsEntity) getFromFile(pathStr string) (*Pattern, error) {
func (o *PatternsEntity) getFromFile(pathStr string) (pattern *Pattern, err error) {
// Handle home directory expansion
if strings.HasPrefix(pathStr, "~/") {
homedir, err := os.UserHomeDir()
if err != nil {
return nil, fmt.Errorf("could not get home directory: %v", err)
var homedir string
if homedir, err = os.UserHomeDir(); err != nil {
err = fmt.Errorf("could not get home directory: %v", err)
return
}
pathStr = filepath.Join(homedir, pathStr[2:])
}
content, err := os.ReadFile(pathStr)
if err != nil {
return nil, fmt.Errorf("could not read pattern file %s: %v", pathStr, err)
var content []byte
if content, err = os.ReadFile(pathStr); err != nil {
err = fmt.Errorf("could not read pattern file %s: %v", pathStr, err)
return
}
return &Pattern{
pattern = &Pattern{
Name: pathStr,
Pattern: string(content),
}, nil
}
return
}
// Get required for Storage interface

View File

@@ -79,7 +79,7 @@ func TestApplyVariables(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := entity.applyVariables(tt.pattern, tt.variables, tt.input)
err := entity.applyVariables(tt.pattern, tt.variables, tt.input)
if tt.wantErr {
assert.Error(t, err)
@@ -87,7 +87,7 @@ func TestApplyVariables(t *testing.T) {
}
assert.NoError(t, err)
assert.Equal(t, tt.want, result.Pattern)
assert.Equal(t, tt.want, tt.pattern.Pattern)
})
}
}

View File

@@ -58,8 +58,7 @@ func (o *Session) Append(messages ...*goopenai.ChatCompletionMessage) {
}
func (o *Session) GetVendorMessages() (ret []*goopenai.ChatCompletionMessage) {
if o.vendorMessages == nil {
o.vendorMessages = []*goopenai.ChatCompletionMessage{}
if len(o.vendorMessages) == 0 {
for _, message := range o.Messages {
o.appendVendorMessage(message)
}

View File

@@ -1,3 +1,3 @@
package main
var version = "v1.4.114"
var version = "v1.4.118"

View File

@@ -10,14 +10,4 @@ The goal of this app is to not only provide a user interface for Fabric, but als
### Installing
It can be installed by navigating to the `web` directory and using `npm install`, `pnpm install`, or your favorite package manager. Then simply run `npm run dev` or your equivalent command to start the app. *You will need to run fabric in a seperate terminal with the `fabric --serve` command.*
### Todos
- [ ] Remove dead code
- [ ] Add feat: Add copy button / load button to load blog posts to the Chat and Chat to Blog posts (system message or user?)
- [ ] Add feat: Jina button
- [ ] Fix save button to save markdown, not json
- [ ] Implement session handling
- [?] What will I do with the context?
- [ ] Add support for image uploads / file uploads
### Collaborators
There are many experienced developers in the Fabric community. If you'd like to collaborate on this project, please reach out to me on.