Skip to content

Commit

Permalink
πŸ”¨ several code refactorings
Browse files Browse the repository at this point in the history
  • Loading branch information
yusufcanb committed Feb 23, 2024
1 parent 39792b9 commit eea274a
Show file tree
Hide file tree
Showing 7 changed files with 182 additions and 68 deletions.
8 changes: 4 additions & 4 deletions app/Modelfile.explain
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
FROM codellama:7b

PARAMETER temperature 0.3
PARAMETER top_p 0.5
PARAMETER top_k 40
PARAMETER temperature 0.25
PARAMETER top_p 0.2
PARAMETER top_k 25
PARAMETER seed 42

SYSTEM You will be explaining given executable shell command to user with shortest possible explanation. If given input is not a shell command, you will respond with "I can only explain shell commands. Please provide a shell command to explain."
SYSTEM You are a command line application which helps user to get brief explanations for shell commands. You will be explaining given executable shell command to user with shortest possible explanation. If given input is not a shell command, you will respond with "I can only explain shell commands. Please provide a shell command to explain". You will never respond any question out of shell command explanation context.
4 changes: 2 additions & 2 deletions explain/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,15 @@ func (e *Explain) getParametersFor(preference string) map[string]interface{} {
}
}

func (e *Explain) streamExplanationFor(mode, prompt string) error {
func (e *Explain) StreamExplanationFor(mode, prompt string) error {
onResponseFunc := func(res ollama.GenerateResponse) error {
fmt.Print(res.Response)
return nil
}

err := e.api.Generate(context.Background(), &ollama.GenerateRequest{
Model: "explain:7b",
Prompt: "Explain the command briefly: " + prompt,
Prompt: "Explain command: " + prompt,
Options: e.getParametersFor(mode),
}, onResponseFunc)

Expand Down
22 changes: 19 additions & 3 deletions explain/cli.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,34 @@
package explain

import (
"context"
"fmt"
"github.com/urfave/cli/v2"
"github.com/yusufcanb/tlm/shell"
"os"
)

func (e *Explain) Action(c *cli.Context) error {
return e.streamExplanationFor(Balanced, c.Args().Get(0))
func (e *Explain) before(_ *cli.Context) error {
_, err := e.api.Version(context.Background())
if err != nil {
fmt.Println(shell.Err() + " " + err.Error())
fmt.Println(shell.Err() + " Ollama connection failed. Please check your Ollama configuration or execute `tlm install`")
os.Exit(-1)
}

return nil
}

func (e *Explain) action(c *cli.Context) error {
return e.StreamExplanationFor(Balanced, c.Args().Get(0))
}

func (e *Explain) Command() *cli.Command {
return &cli.Command{
Name: "explain",
Aliases: []string{"e"},
Usage: "explain a command.",
Action: e.Action,
Before: e.before,
Action: e.action,
}
}
135 changes: 92 additions & 43 deletions install/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import (
"context"
"errors"
"fmt"
"github.com/charmbracelet/huh/spinner"
ollama "github.com/jmorganca/ollama/api"
"github.com/yusufcanb/tlm/shell"
"os"
"os/exec"
"strings"
)
Expand Down Expand Up @@ -34,8 +37,12 @@ func (i *Install) createVolume(volumeName string) error {
return nil
}

func (i *Install) installModelfile(modelfile string) error {
return nil
func (i *Install) installModelfile(name, modelfile string) error {
var err error
err = i.api.Create(context.Background(), &ollama.CreateRequest{Model: name, Modelfile: modelfile}, func(res ollama.ProgressResponse) error {
return nil
})
return err
}

func (i *Install) removeContainer(containerName string) error {
Expand All @@ -46,71 +53,113 @@ func (i *Install) removeContainer(containerName string) error {
return nil
}

func (i *Install) createContainer(containerName string) error {
return nil
func (i *Install) createContainer(containerName string, gpuEnabled bool) (string, error) {
var cmd *exec.Cmd

withCPU := []string{"run", "-d", "--gpus=all",
"-v", "ollama:/root/.ollama", "-p", "11434:11434", "--name", containerName, "ollama/ollama"}

withGPU := []string{"run", "-d", "--gpus=all",
"-v", "ollama:/root/.ollama", "-p", "11434:11434", "--name", containerName, "ollama/ollama"}

if gpuEnabled {
cmd = exec.Command("docker", withGPU...)
} else {
cmd = exec.Command("docker", withCPU...)

}

cmd = exec.Command("docker", "run", "-d", "--gpus=all",
"-v", "ollama:/root/.ollama", "-p", "11434:11434", "--name", containerName, "ollama/ollama")

stdout, stderr := cmd.CombinedOutput()
if stderr != nil {
return "", errors.New(stderr.Error())
}

return string(stdout), nil
}

func (i *Install) installAndConfigureOllama(form *InstallForm2) error {
fmt.Println("Installing and configuring Ollama...")

// 1. Check if Ollama volume exists
if !i.isVolumeInstalled(form.ollamaVolume) {
fmt.Println("Ollama volume not found. Creating a new volume.")
if err := i.createVolume(form.ollamaVolume); err != nil {
return fmt.Errorf("error creating volume: %v", err)
}
} else {
fmt.Println("Ollama volume found. Using existing volume.")
}
i.checkOllamaVolumeExists(form)

// 2. Check if Ollama container exists
containerExists, err := i.isContainerRunning(i.defaultContainerName)
if err != nil {
return fmt.Errorf("error checking for existing container: %v", err)
return fmt.Errorf("- Checking for existing container: %s", shell.Err())
}

// 3. Remove old container (if it exists) and recreate
if containerExists {
fmt.Println("Existing Ollama container found. Removing and recreating.")
fmt.Println("- Existing Ollama container found, removing and re-creating. " + shell.Ok())
if err := i.removeContainer(i.defaultContainerName); err != nil {
return fmt.Errorf("error removing existing container: %v", err)
}
}

// 4. Run the Docker command
cmd := exec.Command("docker", "run", "-d", "--gpus=all",
"-v", "ollama:/root/.ollama", "-p", "11434:11434", "--name", "ollama", "ollama/ollama")

stdout, stderr := cmd.CombinedOutput()
if stderr != nil {
return errors.New(stderr.Error())
}
fmt.Println(string(stdout))
var containerId string
_ = spinner.New().Type(spinner.Line).Title(" Creating Ollama container").Action(func() {
containerId, err = i.createContainer(i.defaultContainerName, form.gpuEnabled)
if err != nil {
fmt.Printf("- Creating Ollama container... %s", shell.Err())
fmt.Println(err.Error())
os.Exit(-1)
}
}).Run()
fmt.Printf("- Creating Ollama container... %s %s", containerId, shell.Ok())

// 5. Pull CodeLLaMa if not exists
onProgressResponse := func(res ollama.ProgressResponse) error {
return nil
}

err = i.api.Pull(context.Background(), &ollama.PullRequest{Model: "codellama:7b"}, onProgressResponse)
if err != nil {
return err
}
i.installCodeLLaMa()

// 6. Install the modelfile (Suggest)
onModelResponse := func(res ollama.ProgressResponse) error {
return nil
}

err = i.api.Create(context.Background(), &ollama.CreateRequest{Model: "suggest:7b", Modelfile: form.suggestModelfile}, onModelResponse)
if err != nil {
return err
}
_ = spinner.New().Type(spinner.Line).Title(" Creating Modelfile for suggestions").Action(func() {
err = i.installModelfile("suggest:7b", form.suggestModelfile)
if err != nil {
fmt.Println("- Creating Modelfile for suggestions... " + shell.Err())
os.Exit(-1)
}
}).Run()
fmt.Println("- Creating Modelfile for suggestions... " + shell.Ok())

// 7. Install the modelfile (Suggest)
err = i.api.Create(context.Background(), &ollama.CreateRequest{Model: "explain:7b", Modelfile: form.explainModelfile}, onModelResponse)
if err != nil {
return err
}
_ = spinner.New().Type(spinner.Line).Title(" Creating Modelfile for explanations").Action(func() {
err = i.installModelfile("suggest:7b", form.suggestModelfile)
if err != nil {
fmt.Println("- Creating Modelfile for explanations... " + shell.Err())
os.Exit(-1)
}
}).Run()
fmt.Println("- Creating Modelfile for explanations... " + shell.Ok())

return nil
}

func (i *Install) installCodeLLaMa() {
var err error
_ = spinner.New().Type(spinner.Line).Title(" Installing CodeLLaMa").Action(func() {
err = i.api.Pull(context.Background(), &ollama.PullRequest{Model: "codellama:7b"}, func(res ollama.ProgressResponse) error {
return nil
})
if err != nil {
fmt.Println("- Installing CodeLLaMa... " + shell.Err())
os.Exit(-1)
}
}).Run()

fmt.Println("- Installing CodeLLaMa... " + shell.Ok())
}

func (i *Install) checkOllamaVolumeExists(form *InstallForm2) {
if !i.isVolumeInstalled(form.ollamaVolume) {
fmt.Println("- Ollama volume not found, creating a new volume. " + shell.Ok())
if err := i.createVolume(form.ollamaVolume); err != nil {
fmt.Printf("- Error creating volume: %v", err)
os.Exit(-1)
}
} else {
fmt.Println("- Ollama volume found. Using existing volume. " + shell.Ok())
}
}
6 changes: 6 additions & 0 deletions shell/shell.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ func SuccessMessage(message string) string {
return style.Render(message)
}

func WarnMessage(message string) string {
style := lipgloss.NewStyle()
style = style.Foreground(lipgloss.Color("5"))
return style.Render(message)
}

func Err() string {
style := lipgloss.NewStyle()

Expand Down
50 changes: 41 additions & 9 deletions suggest/cli.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,31 @@
package suggest

import (
"context"
"errors"
"fmt"
"github.com/charmbracelet/huh/spinner"
"github.com/charmbracelet/lipgloss"
"github.com/spf13/viper"
"github.com/urfave/cli/v2"
"github.com/yusufcanb/tlm/explain"
"github.com/yusufcanb/tlm/shell"
"os"
"time"
)

func (s *Suggest) Action(c *cli.Context) error {
func (s *Suggest) before(_ *cli.Context) error {
_, err := s.api.Version(context.Background())
if err != nil {
fmt.Println(shell.Err() + " " + err.Error())
fmt.Println(shell.Err() + " Ollama connection failed. Please check your Ollama configuration or execute `tlm install`")
os.Exit(-1)
}

return nil
}

func (s *Suggest) action(c *cli.Context) error {
var responseText string
var err error

Expand All @@ -33,29 +47,46 @@ func (s *Suggest) Action(c *cli.Context) error {
fmt.Println(shell.Err()+" error getting suggestion:", err)
}

fmt.Printf("┃ >"+" Thinking... %s\n", shell.SuccessMessage("("+t2.Sub(t1).String()+")"))
fmt.Printf(shell.SuccessMessage("┃ >")+" Thinking... (%s)\n", t2.Sub(t1).String())
form := NewCommandForm(s.extractCommandsFromResponse(responseText)[0])
err = form.Run()

fmt.Println(shell.SuccessMessage("┃ > ") + form.command)
if err != nil {
fmt.Println(shell.Err() + " " + err.Error())
fmt.Println(shell.WarnMessage("┃ > ") + "Aborted..." + "\n")
return nil
}

fmt.Println("┃ > " + form.command + "\n")
if form.confirm {
if form.action == Execute {
fmt.Println(shell.SuccessMessage("┃ > ") + "Executing..." + "\n")
cmd, stdout, stderr := shell.Exec2(form.command)
cmd.Run()
err = cmd.Run()
if err != nil {
return err
}

if stderr.String() != "" {
fmt.Println(stderr.String())
fmt.Println()
return errors.New("command failed")
}

fmt.Println(stdout.String())
return nil
}

fmt.Println("suggestion elapsed time:", t2.Sub(t1))
if form.action == Explain {
fmt.Println(shell.SuccessMessage("┃ > ") + "Explaining..." + "\n")

exp := explain.New(s.api, "")
err = exp.StreamExplanationFor(Stable, form.command)
if err != nil {
return err
}

} else {
fmt.Println(shell.WarnMessage("┃ > ") + "Aborted..." + "\n")
}

return nil
}

Expand All @@ -64,6 +95,7 @@ func (s *Suggest) Command() *cli.Command {
Name: "suggest",
Aliases: []string{"s"},
Usage: "suggest a command.",
Action: s.Action,
Before: s.before,
Action: s.action,
}
}
Loading

0 comments on commit eea274a

Please sign in to comment.