Compare commits

...

14 Commits

Author SHA1 Message Date
github-actions[bot]
70d43c5252 Update version to v1.4.52 and commit 2024-10-06 19:50:30 +00:00
Daniel Miessler
fd8216f1bd Merge branch 'main' of github.com:danielmiessler/fabric 2024-10-06 12:50:12 -07:00
Daniel Miessler
ae0c9009d9 Added extract_core_message. 2024-10-06 12:50:05 -07:00
github-actions[bot]
0b26b930f9 Update version to v1.4.51 and commit 2024-10-05 16:48:46 +00:00
Eugen Eisler
5dbaf4f28f fix: tests 2024-10-05 18:48:22 +02:00
github-actions[bot]
1d9cce5adf Update version to v1.4.50 and commit 2024-10-05 16:44:19 +00:00
Eugen Eisler
76622105e2 fix: windows release 2024-10-05 18:43:54 +02:00
github-actions[bot]
e6e3e34f53 Update version to v1.4.49 and commit 2024-10-05 16:42:19 +00:00
Eugen Eisler
7192ddbaa6 fix: windows release 2024-10-05 18:41:58 +02:00
github-actions[bot]
b5206d1923 Update version to v1.4.48 and commit 2024-10-05 15:54:01 +00:00
Eugen Eisler
81d60b4292 feat: Add 'meta' role to store meta info to session, like source of input content. 2024-10-05 17:53:48 +02:00
github-actions[bot]
ca6660585d Update version to v1.4.47 and commit 2024-10-05 15:43:21 +00:00
Eugen Eisler
d70e7c570d feat: Add 'meta' role to store meta info to session, like source of input content. 2024-10-05 17:42:57 +02:00
Eugen Eisler
4fb965ec9d feat: Add 'meta' role to store meta info to session, like source of input content. 2024-10-05 17:33:27 +02:00
12 changed files with 152 additions and 120 deletions

View File

@@ -94,11 +94,19 @@ jobs:
path: fabric-windows-${{ matrix.arch }}.exe
- name: Get latest tag
if: matrix.os != 'windows-latest'
id: get_latest_tag
run: |
latest_tag=$(git tag --sort=-creatordate | head -n 1)
echo "latest_tag=$latest_tag" >> $GITHUB_ENV
- name: Get latest tag
if: matrix.os == 'windows-latest'
id: get_latest_tag_windows
run: |
$latest_tag = git tag --sort=-creatordate | Select-Object -First 1
Add-Content -Path $env:GITHUB_ENV -Value "latest_tag=$latest_tag"
- name: Create release if it doesn't exist
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -208,18 +208,17 @@ fabric -h
```bash
usage: fabric -h
Usage:
fabric [OPTIONS]
Application Options:
-p, --pattern= Choose a pattern
-p, --pattern= Choose a pattern from the available patterns
-v, --variable= Values for pattern variables, e.g. -v=$name:John -v=$age:30
-C, --context= Choose a context
--session= Choose a session
-C, --context= Choose a context from the available contexts
--session= Choose a session from the available sessions
-S, --setup Run setup for all reconfigurable parts of fabric
--setup-skip-patterns Run Setup for specific vendor, one of Ollama, OpenAI, Anthropic, Azure, Gemini, Groq, Mistral, OpenRouter, SiliconCloud. E.g. fabric --setup-vendor=OpenAI
--setup-vendor= Run Setup for specific vendor. E.g. --setup-vendor=OpenAI
--setup-skip-patterns Run Setup for all reconfigurable parts of fabric except patterns update
--setup-vendor= Run Setup for specific vendor, one of Ollama, OpenAI, Anthropic, Azure, Gemini, Groq, Mistral, OpenRouter, SiliconCloud. E.g. fabric --setup-vendor=OpenAI
-t, --temperature= Set temperature (default: 0.7)
-T, --topp= Set top P (default: 0.9)
-s, --stream Stream
@@ -234,7 +233,7 @@ Application Options:
-c, --copy Copy to clipboard
-m, --model= Choose model
-o, --output= Output to file
--output-prompt Output the used prompt (or entire session) before the result
--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
@@ -253,7 +252,7 @@ Application Options:
--version Print current version
Help Options:
-h, --help Show this help message
-h, --help Show this help message
```

View File

@@ -208,7 +208,7 @@ func Cli(version string) (err error) {
}
var session *db.Session
if session, err = chatter.Send(currentFlags.BuildChatRequest(), currentFlags.BuildChatOptions()); err != nil {
if session, err = chatter.Send(currentFlags.BuildChatRequest(strings.Join(os.Args[1:], " ")), currentFlags.BuildChatOptions()); err != nil {
return
}
@@ -228,7 +228,7 @@ func Cli(version string) (err error) {
// if the output flag is set, create an output file
if currentFlags.Output != "" {
if currentFlags.OutputPrompt {
if currentFlags.OutputSession {
sessionAsString := session.String()
err = fabric.CreateOutputFile(sessionAsString, currentFlags.Output)
} else {

View File

@@ -14,13 +14,13 @@ import (
// Flags create flags struct. the users flags go into this, this will be passed to the chat struct in cli
type Flags struct {
Pattern string `short:"p" long:"pattern" description:"Choose a pattern" default:""`
Pattern string `short:"p" long:"pattern" description:"Choose a pattern from the available patterns" default:""`
PatternVariables map[string]string `short:"v" long:"variable" description:"Values for pattern variables, e.g. -v=$name:John -v=$age:30"`
Context string `short:"C" long:"context" description:"Choose a context" default:""`
Session string `long:"session" description:"Choose a session"`
Context string `short:"C" long:"context" description:"Choose a context from the available contexts" default:""`
Session string `long:"session" description:"Choose a session from the available sessions"`
Setup bool `short:"S" long:"setup" description:"Run setup for all reconfigurable parts of fabric"`
SetupSkipPatterns bool `long:"setup-skip-patterns" description:"Run Setup for specific vendor, one of Ollama, OpenAI, Anthropic, Azure, Gemini, Groq, Mistral, OpenRouter, SiliconCloud. E.g. fabric --setup-vendor=OpenAI"`
SetupVendor string `long:"setup-vendor" description:"Run Setup for specific vendor. E.g. --setup-vendor=OpenAI"`
SetupSkipPatterns bool `long:"setup-skip-patterns" description:"Run Setup for all reconfigurable parts of fabric except patterns update"`
SetupVendor string `long:"setup-vendor" description:"Run Setup for specific vendor, one of Ollama, OpenAI, Anthropic, Azure, Gemini, Groq, Mistral, OpenRouter, SiliconCloud. E.g. fabric --setup-vendor=OpenAI"`
Temperature float64 `short:"t" long:"temperature" description:"Set temperature" default:"0.7"`
TopP float64 `short:"T" long:"topp" description:"Set top P" default:"0.9"`
Stream bool `short:"s" long:"stream" description:"Stream"`
@@ -36,7 +36,7 @@ type Flags struct {
Copy bool `short:"c" long:"copy" description:"Copy to clipboard"`
Model string `short:"m" long:"model" description:"Choose model"`
Output string `short:"o" long:"output" description:"Output to file" default:""`
OutputPrompt bool `long:"output-prompt" description:"Output the used prompt (or entire session) before the result"`
OutputSession bool `long:"output-session" description:"Output the entire session (also a temporary one) to the output file"`
LatestPatterns string `short:"n" long:"latest" description:"Number of latest patterns to list" default:"0"`
ChangeDefaultModel bool `short:"d" long:"changeDefaultModel" description:"Change default model"`
YouTube string `short:"y" long:"youtube" description:"YouTube video \"URL\" to grab transcript, comments from it and send to chat"`
@@ -113,13 +113,14 @@ func (o *Flags) BuildChatOptions() (ret *common.ChatOptions) {
return
}
func (o *Flags) BuildChatRequest() (ret *common.ChatRequest) {
func (o *Flags) BuildChatRequest(Meta string) (ret *common.ChatRequest) {
ret = &common.ChatRequest{
ContextName: o.Context,
SessionName: o.Session,
PatternName: o.Pattern,
PatternVariables: o.PatternVariables,
Message: o.Message,
Meta: Meta,
}
if o.Language != "" {
langTag, err := language.Parse(o.Language)

View File

@@ -101,7 +101,8 @@ func TestBuildChatRequest(t *testing.T) {
SessionName: "test-session",
PatternName: "test-pattern",
Message: "test-message",
Meta: "test",
}
request := flags.BuildChatRequest()
request := flags.BuildChatRequest("test")
assert.Equal(t, expectedRequest, request)
}

View File

@@ -2,6 +2,8 @@ package common
import goopenai "github.com/sashabaranov/go-openai"
const ChatMessageRoleMeta = "meta"
type Message struct {
Role string `json:"role"`
Content string `json:"content"`
@@ -14,6 +16,7 @@ type ChatRequest struct {
PatternVariables map[string]string
Message string
Language string
Meta string
}
type ChatOptions struct {

View File

@@ -7,6 +7,7 @@ import (
"github.com/danielmiessler/fabric/db"
"github.com/danielmiessler/fabric/vendors"
goopenai "github.com/sashabaranov/go-openai"
"strings"
)
type Chatter struct {
@@ -20,12 +21,7 @@ type Chatter struct {
}
func (o *Chatter) Send(request *common.ChatRequest, opts *common.ChatOptions) (session *db.Session, err error) {
var chatRequest *Chat
if chatRequest, err = o.NewChat(request); err != nil {
return
}
if session, err = chatRequest.BuildChatSession(opts.Raw); err != nil {
if session, err = o.BuildSession(request, opts.Raw); err != nil {
return
}
@@ -38,7 +34,7 @@ func (o *Chatter) Send(request *common.ChatRequest, opts *common.ChatOptions) (s
if o.Stream {
channel := make(chan string)
go func() {
if streamErr := o.vendor.SendStream(session.Messages, opts, channel); streamErr != nil {
if streamErr := o.vendor.SendStream(session.GetVendorMessages(), opts, channel); streamErr != nil {
channel <- streamErr.Error()
}
}()
@@ -48,7 +44,7 @@ func (o *Chatter) Send(request *common.ChatRequest, opts *common.ChatOptions) (s
fmt.Print(response)
}
} else {
if message, err = o.vendor.Send(context.Background(), session.Messages, opts); err != nil {
if message, err = o.vendor.Send(context.Background(), session.GetVendorMessages(), opts); err != nil {
return
}
}
@@ -60,35 +56,39 @@ func (o *Chatter) Send(request *common.ChatRequest, opts *common.ChatOptions) (s
session.Append(&common.Message{Role: goopenai.ChatMessageRoleAssistant, Content: message})
if chatRequest.Session != nil {
if session.Name != "" {
err = o.db.Sessions.SaveSession(session)
}
return
}
func (o *Chatter) NewChat(request *common.ChatRequest) (ret *Chat, err error) {
ret = &Chat{
Language: request.Language,
}
if request.ContextName != "" {
var ctx *db.Context
if ctx, err = o.db.Contexts.GetContext(request.ContextName); err != nil {
err = fmt.Errorf("could not find context %s: %v", request.ContextName, err)
return
}
ret.Context = ctx.Content
}
func (o *Chatter) BuildSession(request *common.ChatRequest, raw bool) (session *db.Session, err error) {
if request.SessionName != "" {
var sess *db.Session
if sess, err = o.db.Sessions.GetOrCreateSession(request.SessionName); err != nil {
err = fmt.Errorf("could not find session %s: %v", request.SessionName, err)
return
}
ret.Session = sess
session = sess
} else {
session = &db.Session{}
}
if request.Meta != "" {
session.Append(&common.Message{Role: common.ChatMessageRoleMeta, Content: request.Meta})
}
var contextContent string
if request.ContextName != "" {
var ctx *db.Context
if ctx, err = o.db.Contexts.GetContext(request.ContextName); err != nil {
err = fmt.Errorf("could not find context %s: %v", request.ContextName, err)
return
}
contextContent = ctx.Content
}
var patternContent string
if request.PatternName != "" {
var pattern *db.Pattern
if pattern, err = o.db.Patterns.GetPattern(request.PatternName, request.PatternVariables); err != nil {
@@ -97,18 +97,34 @@ func (o *Chatter) NewChat(request *common.ChatRequest) (ret *Chat, err error) {
}
if pattern.Pattern != "" {
ret.Pattern = pattern.Pattern
patternContent = pattern.Pattern
}
}
ret.Message = request.Message
systemMessage := strings.TrimSpace(contextContent) + strings.TrimSpace(patternContent)
if request.Language != "" {
systemMessage = fmt.Sprintf("%s. Please use the language '%s' for the output.", systemMessage, request.Language)
}
userMessage := strings.TrimSpace(request.Message)
if raw {
// use the user role instead of the system role in raw mode
message := systemMessage + userMessage
if message != "" {
session.Append(&common.Message{Role: goopenai.ChatMessageRoleUser, Content: message})
}
} else {
if systemMessage != "" {
session.Append(&common.Message{Role: goopenai.ChatMessageRoleSystem, Content: systemMessage})
}
if userMessage != "" {
session.Append(&common.Message{Role: goopenai.ChatMessageRoleUser, Content: userMessage})
}
}
if session.IsEmpty() {
session = nil
err = fmt.Errorf(NoSessionPatternUserMessages)
}
return
}
type Chat struct {
Context string
Pattern string
Message string
Session *db.Session
Language string
}

View File

@@ -1,21 +0,0 @@
package core
import (
"testing"
)
func TestBuildChatSession(t *testing.T) {
chat := &Chat{
Context: "test context",
Pattern: "test pattern",
Message: "test message",
}
session, err := chat.BuildChatSession(false)
if err != nil {
t.Fatalf("BuildChatSession() error = %v", err)
}
if session == nil {
t.Fatalf("BuildChatSession() returned nil session")
}
}

View File

@@ -3,14 +3,6 @@ package core
import (
"bytes"
"fmt"
"os"
"strconv"
"strings"
"github.com/danielmiessler/fabric/vendors/groq"
"github.com/danielmiessler/fabric/vendors/mistral"
goopenai "github.com/sashabaranov/go-openai"
"github.com/atotto/clipboard"
"github.com/danielmiessler/fabric/common"
"github.com/danielmiessler/fabric/db"
@@ -19,12 +11,16 @@ import (
"github.com/danielmiessler/fabric/vendors/azure"
"github.com/danielmiessler/fabric/vendors/dryrun"
"github.com/danielmiessler/fabric/vendors/gemini"
"github.com/danielmiessler/fabric/vendors/groq"
"github.com/danielmiessler/fabric/vendors/mistral"
"github.com/danielmiessler/fabric/vendors/ollama"
"github.com/danielmiessler/fabric/vendors/openai"
"github.com/danielmiessler/fabric/vendors/openrouter"
"github.com/danielmiessler/fabric/vendors/siliconcloud"
"github.com/danielmiessler/fabric/youtube"
"github.com/pkg/errors"
"os"
"strconv"
)
const DefaultPatternsGitRepoUrl = "https://github.com/danielmiessler/fabric.git"
@@ -257,39 +253,3 @@ func (o *Fabric) CreateOutputFile(message string, fileName string) (err error) {
}
return
}
func (o *Chat) BuildChatSession(raw bool) (ret *db.Session, err error) {
// new messages will be appended to the session and used to send the message
if o.Session != nil {
ret = o.Session
} else {
ret = &db.Session{}
}
systemMessage := strings.TrimSpace(o.Context) + strings.TrimSpace(o.Pattern)
if o.Language != "" {
systemMessage = fmt.Sprintf("%s. Please use the language '%s' for the output.", systemMessage, o.Language)
}
userMessage := strings.TrimSpace(o.Message)
if raw {
// use the user role instead of the system role in raw mode
message := systemMessage + userMessage
if message != "" {
ret.Append(&common.Message{Role: goopenai.ChatMessageRoleUser, Content: message})
}
} else {
if systemMessage != "" {
ret.Append(&common.Message{Role: goopenai.ChatMessageRoleSystem, Content: systemMessage})
}
if userMessage != "" {
ret.Append(&common.Message{Role: goopenai.ChatMessageRoleUser, Content: userMessage})
}
}
if ret.IsEmpty() {
ret = nil
err = fmt.Errorf(NoSessionPatternUserMessages)
}
return
}

View File

@@ -37,6 +37,8 @@ func (o *Sessions) SaveSession(session *Session) (err error) {
type Session struct {
Name string
Messages []*common.Message
vendorMessages []*common.Message
}
func (o *Session) IsEmpty() bool {
@@ -44,7 +46,31 @@ func (o *Session) IsEmpty() bool {
}
func (o *Session) Append(messages ...*common.Message) {
o.Messages = append(o.Messages, messages...)
if o.vendorMessages != nil {
for _, message := range messages {
o.Messages = append(o.Messages, message)
o.appendVendorMessage(message)
}
} else {
o.Messages = append(o.Messages, messages...)
}
}
func (o *Session) GetVendorMessages() (ret []*common.Message) {
if o.vendorMessages == nil {
o.vendorMessages = []*common.Message{}
for _, message := range o.Messages {
o.appendVendorMessage(message)
}
}
ret = o.vendorMessages
return
}
func (o *Session) appendVendorMessage(message *common.Message) {
if message.Role != common.ChatMessageRoleMeta {
o.vendorMessages = append(o.vendorMessages, message)
}
}
func (o *Session) GetLastMessage() (ret *common.Message) {
@@ -56,7 +82,7 @@ func (o *Session) GetLastMessage() (ret *common.Message) {
func (o *Session) String() (ret string) {
for _, message := range o.Messages {
ret += fmt.Sprintf("\n\n\n[%v]>> \n\n\n%v", message.Role, message.Content)
ret += fmt.Sprintf("\n--- \n[%v]\n\n%v", message.Role, message.Content)
}
return
}

View File

@@ -0,0 +1,39 @@
# IDENTITY
You are an expert at looking at a presentation, an essay, or a full body of lifetime work, and clearly and accurately articulating what the core message is.
# GOAL
- Produce a clear sentence that perfectly articulates the core message as presented in a given text or body of work.
# EXAMPLE
If the input is all of Victor Frankl's work, then the core message would be:
Finding meaning in suffering is key to human resilience, purpose, and enduring lifes challenges.
END EXAMPLE
# STEPS
- Fully digest the input.
- Determine if the input is a single text or a body of work.
- Based on which it is, parse the thing that's supposed to be parsed.
- Extract the core message from the parsed text into a single sentence.
# OUTPUT
- Output a single, 15-word sentence that perfectly articulates the core message as presented in the input.
# OUTPUT INSTRUCTIONS
- The sentence should be a single sentence that is 15 words or fewer, with no special formatting or anything else.
- Do not include any setup to the sentence, e.g., "The core message is to…", etc. Just list the core message and nothing else.
- ONLY OUTPUT THE CORE MESSAGE, not a setup to it, commentary on it, or anything else.
- Do not ask questions or complain in any way about the task.

View File

@@ -1,3 +1,3 @@
package main
var version = "v1.4.46"
var version = "v1.4.52"