diff --git a/README.md b/README.md index 6eb9e21306..06b4be4503 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ - **Store models in a central location.** Never again will you have to hunt for the right model file on S3 and figure out the right code to load it. Cog models are in one place with a content-addressable ID. - **Package everything that a model needs to run.** Code, weights, pre/post-processing, data types, Python dependencies, system dependencies, CUDA version, etc etc. No more dependency hell. -- **Let anyone ship models to production.** Cog packages can be deployed to anywhere that runs Docker images, without having to understand Dockerfiles, CUDA, and all that horrible stuff. +- **Let anyone ship models to production.** Cog models can be deployed to anywhere that runs Docker images, without having to understand Dockerfiles, CUDA, and all that horrible stuff. ## How does it work? @@ -48,9 +48,9 @@ $ cog build This has: -- **Created a package**, a ZIP file containing your code + weights + environment definition, and assigned it a content-addressable SHA256 ID. -- **Pushed this package up to a central registry** so it never gets lost and can be run by anyone. -- **Built two Docker images** (one for CPU and one for GPU) that contains the package in a reproducible environment, with the correct versions of Python, your dependencies, CUDA, etc. +- **Created a model**, a ZIP file containing your code + weights + environment definition, and assigned it a content-addressable SHA256 ID. +- **Pushed this model up to a central registry** so it never gets lost and can be run by anyone. +- **Built two Docker images** (one for CPU and one for GPU) that contains the model in a reproducible environment, with the correct versions of Python, your dependencies, CUDA, etc. ## Install @@ -71,22 +71,22 @@ Then, hook up Cog to the server (replace "localhost" with your server's IP if it cog remote set http://localhost:8080 -Next, let's build a package. We have [some models you can play around with](https://github.com/replicate/cog-examples). Clone that repository (you'll need git-lfs) and then build a package out of a model: +Next, let's build a model. We have [some models you can play around with](https://github.com/replicate/cog-examples). Clone that repository (you'll need git-lfs) and then build a model out of a model: cd example-models/inst-colorization/ cog build This will take a few minutes. In the meantime take a look at `cog.yaml` and `infer.py` to see how it works. -When that has finished, you can run inferences on the built model from any machine that is pointed at the server. Replace the ID with your package's ID, and the file with an image on your disk you want to colorize: +When that has finished, you can run inferences on the built model from any machine that is pointed at the server. Replace the ID with your model's ID, and the file with an image on your disk you want to colorize: cog infer b31f9f72d8f14f0eacc5452e85b05c957b9a8ed9 -i @hotdog.jpg -You can see more details about the package: +You can see more details about the model: cog show b31f9f72d8f14f0eacc5452e85b05c957b9a8ed9 -You can also list the packages for this repo: +You can also list the models for this repo: cog list diff --git a/end-to-end-test/end_to_end_test/test_server.py b/end-to-end-test/end_to_end_test/test_server.py index 95fea8ec29..f677b35c44 100644 --- a/end-to-end-test/end_to_end_test/test_server.py +++ b/end-to-end-test/end_to_end_test/test_server.py @@ -96,32 +96,32 @@ def run(self, text, path): assert out.decode().startswith("Successfully built "), ( out.decode() + " doesn't start with 'Successfully built'" ) - package_id = out.decode().strip().split("Successfully built ")[1] + model_id = out.decode().strip().split("Successfully built ")[1] out, _ = subprocess.Popen( - ["cog", "-r", repo, "show", package_id], stdout=subprocess.PIPE + ["cog", "-r", repo, "show", model_id], stdout=subprocess.PIPE ).communicate() lines = out.decode().splitlines() - assert lines[0] == f"ID: {package_id}" + assert lines[0] == f"ID: {model_id}" assert lines[1] == f"Repo: {user}/{repo_name}" # show without -r out, _ = subprocess.Popen( - ["cog", "show", package_id], + ["cog", "show", model_id], stdout=subprocess.PIPE, cwd=project_dir, ).communicate() lines = out.decode().splitlines() - assert lines[0] == f"ID: {package_id}" + assert lines[0] == f"ID: {model_id}" assert lines[1] == f"Repo: {user}/{repo_name}" out, _ = subprocess.Popen(["cog", "-r", repo, "ls"], stdout=subprocess.PIPE).communicate() lines = out.decode().splitlines() - assert lines[1].startswith(f"{package_id} ") + assert lines[1].startswith(f"{model_id} ") download_dir = tmpdir_factory.mktemp("download") / "my-dir" subprocess.Popen( - ["cog", "-r", repo, "download", "--output-dir", download_dir, package_id], + ["cog", "-r", repo, "download", "--output-dir", download_dir, model_id], stdout=subprocess.PIPE, ).communicate() paths = sorted(glob(str(download_dir / "*.*"))) @@ -146,7 +146,7 @@ def run(self, text, path): "text=baz", "-i", f"path=@{input_path}", - package_id, + model_id, ], stdout=subprocess.PIPE, ).communicate() diff --git a/pkg/cli/benchmark.go b/pkg/cli/benchmark.go index 27716a8739..05ec84d9a5 100644 --- a/pkg/cli/benchmark.go +++ b/pkg/cli/benchmark.go @@ -28,8 +28,8 @@ type BenchmarkResults struct { func newBenchmarkCommand() *cobra.Command { cmd := &cobra.Command{ Use: "benchmark", - Short: "Measure setup and runtime of package, using the first example from config", - RunE: benchmarkPackage, + Short: "Measure setup and runtime of model, using the first example from config", + RunE: benchmarkModel, Args: cobra.ExactArgs(1), } @@ -39,7 +39,7 @@ func newBenchmarkCommand() *cobra.Command { return cmd } -func benchmarkPackage(cmd *cobra.Command, args []string) error { +func benchmarkModel(cmd *cobra.Command, args []string) error { repo, err := getRepo() if err != nil { return err @@ -49,26 +49,26 @@ func benchmarkPackage(cmd *cobra.Command, args []string) error { cli := client.NewClient() console.Info("Starting benchmark of %s:%s", repo, id) - pkg, err := cli.GetPackage(repo, id) + mod, err := cli.GetModel(repo, id) if err != nil { return err } - if len(pkg.Config.Examples) == 0 { - return fmt.Errorf("Package has no examples, cannot run benchmark") + if len(mod.Config.Examples) == 0 { + return fmt.Errorf("Model has no examples, cannot run benchmark") } - pkgDir, err := os.MkdirTemp("/tmp", "benchmark") + modelDir, err := os.MkdirTemp("/tmp", "benchmark") if err != nil { return err } - defer os.RemoveAll(pkgDir) - if err := cli.DownloadPackage(repo, id, pkgDir); err != nil { + defer os.RemoveAll(modelDir) + if err := cli.DownloadModel(repo, id, modelDir); err != nil { return err } results := new(BenchmarkResults) for i := 0; i < benchmarkSetups; i++ { console.Info("Running setup iteration %d", i+1) - if err := runBenchmarkInference(pkg, pkgDir, results, benchmarkRuns); err != nil { + if err := runBenchmarkInference(mod, modelDir, results, benchmarkRuns); err != nil { return err } } @@ -89,18 +89,18 @@ func benchmarkPackage(cmd *cobra.Command, args []string) error { return nil } -func runBenchmarkInference(pkg *model.Model, pkgDir string, results *BenchmarkResults, runIterations int) error { +func runBenchmarkInference(mod *model.Model, modelDir string, results *BenchmarkResults, runIterations int) error { servingPlatform, err := serving.NewLocalDockerPlatform() if err != nil { return err } - example := pkg.Config.Examples[0] - input := serving.NewExampleWithBaseDir(example.Input, pkgDir) + example := mod.Config.Examples[0] + input := serving.NewExampleWithBaseDir(example.Input, modelDir) logWriter := logger.NewConsoleLogger() bootStart := time.Now() - deployment, err := servingPlatform.Deploy(pkg, model.TargetDockerCPU, logWriter) + deployment, err := servingPlatform.Deploy(mod, model.TargetDockerCPU, logWriter) if err != nil { return err } diff --git a/pkg/cli/build.go b/pkg/cli/build.go index 4ff3f3dc7e..3a4a4d467a 100644 --- a/pkg/cli/build.go +++ b/pkg/cli/build.go @@ -16,8 +16,8 @@ import ( func newBuildCommand() *cobra.Command { cmd := &cobra.Command{ Use: "build", - Short: "Build Cog package", - RunE: buildPackage, + Short: "Build Cog model", + RunE: buildModel, Args: cobra.NoArgs, } addRepoFlag(cmd) @@ -25,7 +25,7 @@ func newBuildCommand() *cobra.Command { return cmd } -func buildPackage(cmd *cobra.Command, args []string) error { +func buildModel(cmd *cobra.Command, args []string) error { repo, err := getRepo() if err != nil { return err @@ -43,7 +43,7 @@ func buildPackage(cmd *cobra.Command, args []string) error { console.Info("Uploading %s to %s", projectDir, repo) cli := client.NewClient() - mod, err := cli.UploadPackage(repo, projectDir) + mod, err := cli.UploadModel(repo, projectDir) if err != nil { return err } diff --git a/pkg/cli/delete.go b/pkg/cli/delete.go index 3a428fa190..5cc78f686a 100644 --- a/pkg/cli/delete.go +++ b/pkg/cli/delete.go @@ -11,25 +11,25 @@ import ( func newDeleteCommand() *cobra.Command { cmd := &cobra.Command{ Use: "delete", - Short: "Delete a package", - RunE: deletePackage, + Short: "Delete a model", + RunE: deleteModel, Args: cobra.MinimumNArgs(1), Aliases: []string{"rm"}, } return cmd } -func deletePackage(cmd *cobra.Command, args []string) error { +func deleteModel(cmd *cobra.Command, args []string) error { repo, err := getRepo() if err != nil { return err } cli := client.NewClient() for _, id := range args { - if err := cli.DeletePackage(repo, id); err != nil { + if err := cli.DeleteModel(repo, id); err != nil { return err } - fmt.Printf("Deleted package %s:%s\n", repo, id) + fmt.Printf("Deleted model %s:%s\n", repo, id) } return nil } diff --git a/pkg/cli/download.go b/pkg/cli/download.go index ccd656782d..3470ed87e5 100644 --- a/pkg/cli/download.go +++ b/pkg/cli/download.go @@ -17,8 +17,8 @@ var downloadOutputDir string func newDownloadCommand() *cobra.Command { cmd := &cobra.Command{ Use: "download ", - Short: "Download a model package", - RunE: downloadPackage, + Short: "Download a model", + RunE: downloadModel, Args: cobra.ExactArgs(1), } addRepoFlag(cmd) @@ -28,7 +28,7 @@ func newDownloadCommand() *cobra.Command { return cmd } -func downloadPackage(cmd *cobra.Command, args []string) (err error) { +func downloadModel(cmd *cobra.Command, args []string) (err error) { repo, err := getRepo() if err != nil { return err @@ -58,10 +58,10 @@ func downloadPackage(cmd *cobra.Command, args []string) (err error) { } cli := client.NewClient() - if err := cli.DownloadPackage(repo, id, downloadOutputDir); err != nil { + if err := cli.DownloadModel(repo, id, downloadOutputDir); err != nil { return err } - fmt.Printf("Downloaded package %s into %s\n", id, downloadOutputDir) + fmt.Printf("Downloaded model %s into %s\n", id, downloadOutputDir) return nil } diff --git a/pkg/cli/infer.go b/pkg/cli/infer.go index 04485fd076..06ccc38f13 100644 --- a/pkg/cli/infer.go +++ b/pkg/cli/infer.go @@ -48,11 +48,11 @@ func cmdInfer(cmd *cobra.Command, args []string) error { return err } - packageId := args[0] + modelId := args[0] client := client.NewClient() - fmt.Println("Loading package", packageId) - pkg, err := client.GetPackage(repo, packageId) + fmt.Println("Loading package", modelId) + mod, err := client.GetModel(repo, modelId) if err != nil { return err } @@ -63,7 +63,7 @@ func cmdInfer(cmd *cobra.Command, args []string) error { } logWriter := logger.NewConsoleLogger() // TODO(andreas): GPU inference - deployment, err := servingPlatform.Deploy(pkg, model.TargetDockerCPU, logWriter) + deployment, err := servingPlatform.Deploy(mod, model.TargetDockerCPU, logWriter) if err != nil { return err } diff --git a/pkg/cli/list.go b/pkg/cli/list.go index 1d91dbc42f..2be9fe14e3 100644 --- a/pkg/cli/list.go +++ b/pkg/cli/list.go @@ -15,8 +15,8 @@ import ( func newListCommand() *cobra.Command { cmd := &cobra.Command{ Use: "list", - Short: "List Cog packages", - RunE: listPackages, + Short: "List Cog models", + RunE: listModels, Args: cobra.NoArgs, Aliases: []string{"ls"}, } @@ -25,14 +25,14 @@ func newListCommand() *cobra.Command { return cmd } -func listPackages(cmd *cobra.Command, args []string) error { +func listModels(cmd *cobra.Command, args []string) error { repo, err := getRepo() if err != nil { return err } cli := client.NewClient() - models, err := cli.ListPackages(repo) + models, err := cli.ListModels(repo) if err != nil { return err } diff --git a/pkg/cli/show.go b/pkg/cli/show.go index 875ed5447f..0742bcd82a 100644 --- a/pkg/cli/show.go +++ b/pkg/cli/show.go @@ -14,8 +14,8 @@ import ( func newShowCommand() *cobra.Command { cmd := &cobra.Command{ Use: "show ", - Short: "Inspect a Cog package", - RunE: showPackage, + Short: "Inspect a Cog model", + RunE: showModel, Args: cobra.ExactArgs(1), SuggestFor: []string{"inspect"}, } @@ -24,7 +24,7 @@ func newShowCommand() *cobra.Command { return cmd } -func showPackage(cmd *cobra.Command, args []string) error { +func showModel(cmd *cobra.Command, args []string) error { repo, err := getRepo() if err != nil { return err @@ -33,7 +33,7 @@ func showPackage(cmd *cobra.Command, args []string) error { id := args[0] cli := client.NewClient() - mod, err := cli.GetPackage(repo, id) + mod, err := cli.GetModel(repo, id) if err != nil { return err } diff --git a/pkg/client/delete.go b/pkg/client/delete.go index 41da67c35e..1a785e320b 100644 --- a/pkg/client/delete.go +++ b/pkg/client/delete.go @@ -7,9 +7,8 @@ import ( "github.com/replicate/cog/pkg/model" ) -// The URL says "package" but the code says "Model", sob -func (c *Client) DeletePackage(repo *model.Repo, id string) error { - url := fmt.Sprintf("http://%s/v1/repos/%s/%s/packages/%s", repo.Host, repo.User, repo.Name, id) +func (c *Client) DeleteModel(repo *model.Repo, id string) error { + url := fmt.Sprintf("http://%s/v1/repos/%s/%s/models/%s", repo.Host, repo.User, repo.Name, id) req, err := http.NewRequest(http.MethodDelete, url, nil) if err != nil { return err diff --git a/pkg/client/download.go b/pkg/client/download.go index 9e593a55f8..1aad591172 100644 --- a/pkg/client/download.go +++ b/pkg/client/download.go @@ -12,8 +12,8 @@ import ( "github.com/replicate/cog/pkg/model" ) -func (c *Client) DownloadPackage(repo *model.Repo, id string, outputDir string) error { - url := fmt.Sprintf("http://%s/v1/repos/%s/%s/packages/%s.zip", repo.Host, repo.User, repo.Name, id) +func (c *Client) DownloadModel(repo *model.Repo, id string, outputDir string) error { + url := fmt.Sprintf("http://%s/v1/repos/%s/%s/models/%s.zip", repo.Host, repo.User, repo.Name, id) req, err := http.NewRequest("GET", url, nil) if err != nil { return fmt.Errorf("Failed to create HTTP request: %w", err) @@ -24,10 +24,10 @@ func (c *Client) DownloadPackage(repo *model.Repo, id string, outputDir string) } if resp.StatusCode == http.StatusNotFound { - return fmt.Errorf("Package ID doesn't exist: %s", id) + return fmt.Errorf("Model ID doesn't exist: %s", id) } if resp.StatusCode != http.StatusOK { - return fmt.Errorf("Package zip endpoint returned status %d", resp.StatusCode) + return fmt.Errorf("Model zip endpoint returned status %d", resp.StatusCode) } bar := progressbar.DefaultBytes( diff --git a/pkg/client/get.go b/pkg/client/get.go index 3fef66a23a..a7fa3f6230 100644 --- a/pkg/client/get.go +++ b/pkg/client/get.go @@ -9,9 +9,8 @@ import ( "github.com/replicate/cog/pkg/model" ) -// The URL says "package" but the code says "Model", sob -func (c *Client) GetPackage(repo *model.Repo, id string) (*model.Model, error) { - url := fmt.Sprintf("http://%s/v1/repos/%s/%s/packages/%s", repo.Host, repo.User, repo.Name, id) +func (c *Client) GetModel(repo *model.Repo, id string) (*model.Model, error) { + url := fmt.Sprintf("http://%s/v1/repos/%s/%s/models/%s", repo.Host, repo.User, repo.Name, id) resp, err := http.Get(url) if err != nil { return nil, err diff --git a/pkg/client/list.go b/pkg/client/list.go index 1ccfbd63de..bf60ae4f8e 100644 --- a/pkg/client/list.go +++ b/pkg/client/list.go @@ -8,8 +8,8 @@ import ( "github.com/replicate/cog/pkg/model" ) -func (c *Client) ListPackages(repo *model.Repo) ([]*model.Model, error) { - url := fmt.Sprintf("http://%s/v1/repos/%s/%s/packages/", repo.Host, repo.User, repo.Name) +func (c *Client) ListModels(repo *model.Repo) ([]*model.Model, error) { + url := fmt.Sprintf("http://%s/v1/repos/%s/%s/models/", repo.Host, repo.User, repo.Name) resp, err := http.Get(url) if err != nil { return nil, err diff --git a/pkg/client/upload.go b/pkg/client/upload.go index 5b47379cf8..3b36d9f7ac 100644 --- a/pkg/client/upload.go +++ b/pkg/client/upload.go @@ -18,12 +18,12 @@ import ( "github.com/replicate/cog/pkg/model" ) -func (c *Client) UploadPackage(repo *model.Repo, projectDir string) (*model.Model, error) { +func (c *Client) UploadModel(repo *model.Repo, projectDir string) (*model.Model, error) { bodyReader, bodyWriter := io.Pipe() client := &http.Client{} - url := fmt.Sprintf("http://%s/v1/repos/%s/%s/packages/", repo.Host, repo.User, repo.Name) + url := fmt.Sprintf("http://%s/v1/repos/%s/%s/models/", repo.Host, repo.User, repo.Name) req, err := http.NewRequest(http.MethodPut, url, bodyReader) if err != nil { return nil, err @@ -51,11 +51,11 @@ func (c *Client) UploadPackage(repo *model.Repo, projectDir string) (*model.Mode } }() go func() { - err := uploadFile(req, "file", "package.zip", zipReader, bodyWriter) + err := uploadFile(req, "file", "model.zip", zipReader, bodyWriter) if err != nil { console.Fatal(err.Error()) } - console.Info("Building package...") + console.Info("Building model...") }() resp, err := client.Do(req) diff --git a/pkg/database/local.go b/pkg/database/local.go index 8ba50f8acd..3f0dff5494 100644 --- a/pkg/database/local.go +++ b/pkg/database/local.go @@ -42,7 +42,7 @@ func (db *LocalFileDatabase) InsertModel(user string, name string, id string, mo if err != nil { return fmt.Errorf("Failed to marshall model: %w", err) } - path := db.packagePath(user, name, id) + path := db.modelPath(user, name, id) dir := filepath.Dir(path) exists, err := files.FileExists(path) if err != nil { @@ -61,7 +61,7 @@ func (db *LocalFileDatabase) InsertModel(user string, name string, id string, mo // GetModel returns a model or nil if the model doesn't exist func (db *LocalFileDatabase) GetModel(user string, name string, id string) (*model.Model, error) { - path := db.packagePath(user, name, id) + path := db.modelPath(user, name, id) exists, err := files.FileExists(path) if err != nil { return nil, fmt.Errorf("Failed to determine if %s exists: %w", path, err) @@ -77,7 +77,7 @@ func (db *LocalFileDatabase) GetModel(user string, name string, id string) (*mod } func (db *LocalFileDatabase) DeleteModel(user string, name string, id string) error { - path := db.packagePath(user, name, id) + path := db.modelPath(user, name, id) if err := os.Remove(path); err != nil { return fmt.Errorf("Failed to delete %s: %w", path, err) } @@ -117,7 +117,7 @@ func (db *LocalFileDatabase) readModel(path string) (*model.Model, error) { return mod, nil } -func (db *LocalFileDatabase) packagePath(user string, name string, id string) string { +func (db *LocalFileDatabase) modelPath(user string, name string, id string) string { return filepath.Join(db.repoDir(user, name), id+".json") } diff --git a/pkg/server/delete.go b/pkg/server/delete.go index 414d6c9545..4d172120a4 100644 --- a/pkg/server/delete.go +++ b/pkg/server/delete.go @@ -6,7 +6,7 @@ import ( "github.com/replicate/cog/pkg/console" ) -func (s *Server) DeletePackage(w http.ResponseWriter, r *http.Request) { +func (s *Server) DeleteModel(w http.ResponseWriter, r *http.Request) { user, name, id := getRepoVars(r) console.Info("Received delete request for %s/%s/%s", user, name, id) diff --git a/pkg/server/download.go b/pkg/server/download.go index ed6b527a03..b3808e08aa 100644 --- a/pkg/server/download.go +++ b/pkg/server/download.go @@ -8,7 +8,7 @@ import ( "github.com/replicate/cog/pkg/console" ) -func (s *Server) SendModelPackage(w http.ResponseWriter, r *http.Request) { +func (s *Server) DownloadModel(w http.ResponseWriter, r *http.Request) { user, name, id := getRepoVars(r) console.Info("Received download request for %s/%s/%s", user, name, id) modTime := time.Now() // TODO diff --git a/pkg/server/list.go b/pkg/server/list.go index 9d88e39865..5ff5d497b5 100644 --- a/pkg/server/list.go +++ b/pkg/server/list.go @@ -7,7 +7,7 @@ import ( "github.com/replicate/cog/pkg/console" ) -func (s *Server) ListPackages(w http.ResponseWriter, r *http.Request) { +func (s *Server) ListModels(w http.ResponseWriter, r *http.Request) { user, name, _ := getRepoVars(r) console.Info("Received list request for %s%s", user, name) diff --git a/pkg/server/server.go b/pkg/server/server.go index e41125d8a7..1fae5f43bb 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -44,21 +44,21 @@ func (s *Server) Start() error { console.Info("Received ping request") w.Write([]byte("pong")) }) - router.Path("/v1/repos/{user}/{name}/packages/{id}.zip"). + router.Path("/v1/repos/{user}/{name}/models/{id}.zip"). Methods(http.MethodGet). - HandlerFunc(s.SendModelPackage) - router.Path("/v1/repos/{user}/{name}/packages/"). + HandlerFunc(s.DownloadModel) + router.Path("/v1/repos/{user}/{name}/models/"). Methods(http.MethodPut). HandlerFunc(s.ReceiveFile) - router.Path("/v1/repos/{user}/{name}/packages/"). + router.Path("/v1/repos/{user}/{name}/models/"). Methods(http.MethodGet). - HandlerFunc(s.ListPackages) - router.Path("/v1/repos/{user}/{name}/packages/{id}"). + HandlerFunc(s.ListModels) + router.Path("/v1/repos/{user}/{name}/models/{id}"). Methods(http.MethodGet). HandlerFunc(s.SendModelMetadata) - router.Path("/v1/repos/{user}/{name}/packages/{id}"). + router.Path("/v1/repos/{user}/{name}/models/{id}"). Methods(http.MethodDelete). - HandlerFunc(s.DeletePackage) + HandlerFunc(s.DeleteModel) fmt.Println("Starting") return http.ListenAndServe(fmt.Sprintf(":%d", s.port), router) }