diff --git a/README.md b/README.md index 75ca1d5..7c2a137 100644 --- a/README.md +++ b/README.md @@ -56,18 +56,60 @@ There are two ways to collaborate and improve the algorithm 4. Use bsctl to dump the keywords to stdout and then copy and past them into [Bluesky Feed Creator](https://blueskyfeedcreator.com/) -## Commands For AIEngineering and PlatformEngineering - -```bash {"id":"01JBTAGCHJ9H72SM46CHAPGPY3"} -cd ~/git_bskylists -git fetch origin -git checkout origin/main -cd ~/git_bskyctl -#make build -.build/bsctl apply ~/git_bskylists/aiengineering.yaml -.build/bsctl apply ~/git_bskylists/platformengineering.yaml +## Identifying Community Members Algorithmically + +Rather than manually curating a list of handles, we can use algorithms to identify community members. +The algorithm is very simple + +1. Take a set of seed handles +1. Fetch the profile for everyone who **follows** those accounts +1. Use an LLM to decide whether the profile satisfies some criterion + +To use this functionality define a `CommunityBuilder` resource in a YAML file like the one below. + +```yaml +apiVersion: "bsctl.dev/v1alpha1" +kind: "CommunityBuilder" +metadata: + labels: {} + name: PlatformCommunity +definition: + name: Platform Engineer + criterion: + - They are working on an internal developer platform + - They describe their job role as platform engineer, ml platform engineer, devops, infrastructure engineer or SRE + - They work with technologies used to build platforms; eg. kubernetes, cloud, argo + - They describe practices central to platform engineering; e.g. IAC, configuration, containers, gitops, cicd + examples: + - profile: I'm a platform engineer at acme.co + member: true + explanation: "" +seeds: + - handle: kelseyhightower.com + did: "" +outputFile: /Users/jlewi/git_bskylists//Users/jlewi/git_bskylists/kelseyhightower.followers.platformengineering.yaml ``` +* Everything in the `definition` section is used as input to the [LLM Prompt](https://github.com/jlewi/bsctl/blob/main/pkg/lists/profile_prompt.tmpl) +* To perform the graph walk first configure your OpenAI APIKey + + ``` + bsctl config set openai.apiKeyFile=/path/to/openai/apikey + ``` + +* You can then perform the graph walk using the CLI + + ``` + bsctl apply /path/to/your/community.yaml + ``` + +* This will write the results to the outputFile you specified +* The output will contain an AccountList that tells you + 1. Whether the account is a member of the community + 1. A reason for the decision + +* For an example of the output see [kelseyhightower.followers.platformengineering.yaml] + ## License MIT diff --git a/cmd/root.go b/cmd/root.go index f92a771..f4ea2f8 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -23,6 +23,7 @@ func NewRootCmd() *cobra.Command { rootCmd.AddCommand(NewConfigCmd()) rootCmd.AddCommand(NewApplyCmd()) rootCmd.AddCommand(NewDumpCmd()) + rootCmd.AddCommand(NewMergeCmd()) rootCmd.AddCommand(NewTidyCmd()) rootCmd.AddCommand(NewDumpStarterPack()) return rootCmd diff --git a/notes/2024_11_09_platform_eng.md b/notes/2024_11_09_platform_eng.md index d1fa54b..db27e94 100644 --- a/notes/2024_11_09_platform_eng.md +++ b/notes/2024_11_09_platform_eng.md @@ -16,6 +16,34 @@ make build ../.build/bsctl tidy /Users/jlewi/git_bskylists/platformengineering.yaml ``` +# Merge Kelsey's list into the platform engineering list + +* How big is the group currently + +```bash +yq ".items | length" /Users/jlewi/git_bskylists/platformengineering.yaml +``` + +```bash {"id":"01JC9VSV7Z96A62PERW4HKY5KT"} +../.build/bsctl merge --dest=/Users/jlewi/git_bskylists/platformengineering.yaml \ + --source=/Users/jlewi/git_bskylists/kelseyhightower.followers.platformengineering.yaml \ + --source-filter=members +``` + +```bash +yq ".items | length" /Users/jlewi/git_bskylists/platformengineering.yaml +``` + +* So it had 204 items before and now it has 548 +* Now lets sync it to bluesky + +```bash +../.build/bsctl apply /Users/jlewi/git_bskylists/platformengineering.yaml +``` + +The error message indicates that the `merge` command is not recognized. This could be due to a few reasons, such as a typo in the command or the version of the `bsctl` tool not supporting the merge functionality. +1. **Check available commands** to ensure that `merge` is a valid command in your current version: + ```bash ``` diff --git a/pkg/api/v1alpha1/accounts.go b/pkg/api/v1alpha1/accounts.go index 1192156..d08c847 100644 --- a/pkg/api/v1alpha1/accounts.go +++ b/pkg/api/v1alpha1/accounts.go @@ -26,12 +26,9 @@ type AccountList struct { // include and exclude list. Items []Membership `json:"items" yaml:"items"` - // TODO(jeremy): Get rid of this; use Accounts + // TODO(jeremy): This field is deprecated. We keep it in only to enable the tidy command to convert to the + // new format which uses Items. Accounts []Account `json:"accounts,omitempty" yaml:"accounts,omitempty"` - - // TODO(jeremy): Get rid of these fields - Members []Membership `json:"members,omitempty" yaml:"members,omitempty"` - Exclude []Membership `json:"exclude,omitempty" yaml:"exclude,omitempty"` } type Membership struct { diff --git a/pkg/lists/controller.go b/pkg/lists/controller.go index b8f3455..8bca32c 100644 --- a/pkg/lists/controller.go +++ b/pkg/lists/controller.go @@ -48,17 +48,6 @@ func (c *AccountListController) Tidy(ctx context.Context, l *v1alpha1.AccountLis accounts[a.Handle] = m } - for _, m := range l.Members { - m.Member = true - accounts[m.Account.Handle] = m - } - - for _, m := range l.Exclude { - m.Member = true - m.Member = false - accounts[m.Account.Handle] = m - } - for _, m := range l.Items { accounts[m.Account.Handle] = m } @@ -79,8 +68,6 @@ func (c *AccountListController) Tidy(ctx context.Context, l *v1alpha1.AccountLis l.Items = members l.Accounts = nil - l.Exclude = nil - l.Members = nil return nil } diff --git a/pkg/lists/walker.go b/pkg/lists/walker.go index 9f6728d..9dfa2aa 100644 --- a/pkg/lists/walker.go +++ b/pkg/lists/walker.go @@ -76,11 +76,7 @@ func (g *GraphWalker) Reconcile(ctx context.Context, buildSpec *v1alpha1.Communi } // Add the list of seen accounts to the account list - for _, member := range accountList.Members { - seen[member.Account.Handle] = true - } - - for _, member := range accountList.Exclude { + for _, member := range accountList.Items { seen[member.Account.Handle] = true } @@ -121,8 +117,9 @@ func (g *GraphWalker) getFollowers(ctx context.Context, definition v1alpha1.Comm DID: f.Did, }, Explanation: "The account has no profile description.", + Member: false, } - accountList.Exclude = append(accountList.Exclude, member) + accountList.Items = append(accountList.Items, member) continue } prompt, err := buildPrompt(definition, *f.Description) @@ -184,12 +181,10 @@ func (g *GraphWalker) getFollowers(ctx context.Context, definition v1alpha1.Comm DID: f.Did, }, Explanation: output.Explanation, + Member: output.Member, } - if output.Member { - accountList.Members = append(accountList.Members, member) - } else { - accountList.Exclude = append(accountList.Exclude, member) - } + + accountList.Items = append(accountList.Items, member) } if err := g.save(ctx, accountList, outputFile); err != nil {