From b409e8f2fd11c62259662a6ef6e7784de96bd6d2 Mon Sep 17 00:00:00 2001 From: Renato Rodrigues de Araujo Date: Sat, 7 Oct 2023 04:43:39 +0100 Subject: [PATCH] minor: experimental integration with openai gpt model 3.5 --- Makefile | 5 +++- cmd/find.go | 22 ++++++++++++++++- go.mod | 1 + go.sum | 2 ++ internal/sponsors/organisation.go | 41 +++++++++++++++++++++++++++++-- 5 files changed, 67 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 6da26da..a698970 100644 --- a/Makefile +++ b/Makefile @@ -3,8 +3,11 @@ build: go build -o sponsors +help: build + @./sponsors help + find: build - @./sponsors find --company $(filter-out $@,$(MAKECMDGOALS)) + @./sponsors find --company $(firstword $(filter-out $@,$(MAKECMDGOALS))) --details $(word 2, $(filter-out $@,$(MAKECMDGOALS))) %: @: \ No newline at end of file diff --git a/cmd/find.go b/cmd/find.go index b046aa4..080f5c3 100644 --- a/cmd/find.go +++ b/cmd/find.go @@ -13,10 +13,18 @@ import ( ) var companyName string +var provideDetails bool +var role string var findCmd = &cobra.Command{ Use: "find", Short: "Find the company by it's name and the type of the Visa they are licensed to provide.", + Long: `Easily verify if a company is a UK Visa sponsor and identify the types of Visas they offer. For deeper insights, leverage information powered by OpenAI GPT. + +Note: Some companies are registered under different names with the government. For instance, you might find 'Facebook' instead of 'Meta'. + +For AI-enhanced details, ensure your search result is unique. Future updates aim to use OpenAI to better match company names in the list. +`, RunE: func(cmd *cobra.Command, args []string) error { p := data.NewCSVProcessor() @@ -36,6 +44,16 @@ var findCmd = &cobra.Command{ quotedVisaTypes[i] = fmt.Sprintf("\"%s\"", v) } color.Green("%s is authorized to sponsor the following visa types: %s.", org.Name, strings.Join(quotedVisaTypes, ", ")) + if provideDetails { + err = org.AddDescription(role) + if err != nil { + fmt.Println() + color.Red("failed to add details of %s; %w", org.Name, err) + } + + color.Cyan("Details:\n%s", org.Description) + } + } fmt.Println() @@ -47,7 +65,9 @@ var findCmd = &cobra.Command{ func init() { rootCmd.AddCommand(findCmd) - findCmd.Flags().StringVarP(&companyName, "company", "c", "", "Company name") + findCmd.Flags().StringVarP(&companyName, "company", "c", "", "Company name.") + findCmd.Flags().BoolVarP(&provideDetails, "details", "d", false, "Provide more details for the company (requires OpenAI token).") + findCmd.Flags().StringVarP(&role, "role", "r", "software engineering", "Role that you're interested.") err := findCmd.MarkFlagRequired("company") if err != nil { log.Fatalf("failed to initialise; %w", err) diff --git a/go.mod b/go.mod index d98a5ef..cf6d469 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.17 // indirect + github.com/sashabaranov/go-openai v1.15.4 // indirect github.com/spf13/pflag v1.0.5 // indirect golang.org/x/sys v0.6.0 // indirect ) diff --git a/go.sum b/go.sum index 33fab66..3029915 100644 --- a/go.sum +++ b/go.sum @@ -9,6 +9,8 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/ github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sashabaranov/go-openai v1.15.4 h1:BXCR0Uxk5RipeY4yBC7g6pBVfcjh8jwrMNOYdie6yuk= +github.com/sashabaranov/go-openai v1.15.4/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg= github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= diff --git a/internal/sponsors/organisation.go b/internal/sponsors/organisation.go index a369c04..d772469 100644 --- a/internal/sponsors/organisation.go +++ b/internal/sponsors/organisation.go @@ -1,6 +1,10 @@ package sponsors import ( + "context" + "fmt" + "github.com/sashabaranov/go-openai" + "os" "strings" ) @@ -9,8 +13,9 @@ type Organisations struct { } type Organisation struct { - Name string - VisaType []string + Name string + VisaType []string + Description string } func (o *Organisations) SearchOrganisationsByName(name string) []Organisation { @@ -39,3 +44,35 @@ func (o *Organisations) AddOrUpdateVisaType(name string, visaType string) { } o.list = append(o.list, newOrg) } + +// TODO: decouple and improve configuration for the command +func (o *Organisation) AddDescription(role string) error { + + message := fmt.Sprintf(`Provide a concise summary (up to 1024 characters) about the company %s based in the UK, focusing on its business nature, core activities, and market reputation, especially in the context of %s. If no details are available, respond with "N/A". +- For insights on the company's culture and its reputation as a desirable workplace for %s, include a section after the main content, formatted as: \nCulture:\n{information}\n. +- If you encounter details about their salary range for %s or if they're recognized for offering competitive salaries in this domain, add a section formatted as: \nSalaries:\n{information}. If no specific salary information is available and the company is a subsidiary, consider information about the parent company's salary reputation for %s roles. +- Provide insights on the hiring process's complexity for %s positions, whether it's challenging to secure such a role, and any preparation time typically required for interviews or technical interviews, formatted as: \nHiring Process:\n{information}. +`, o.Name, o.Name, role, role, role, role) + + client := openai.NewClient(os.Getenv("OPEN_AI_TOKEN")) + resp, err := client.CreateChatCompletion( + context.Background(), + openai.ChatCompletionRequest{ + Model: openai.GPT3Dot5Turbo, + Temperature: 0.0001, + Messages: []openai.ChatCompletionMessage{ + { + Role: openai.ChatMessageRoleSystem, + Content: message, + }, + }, + }, + ) + + if err != nil { + return fmt.Errorf("gpt generation error; %w", err) + } + + o.Description = resp.Choices[0].Message.Content + return nil +}