-
Notifications
You must be signed in to change notification settings - Fork 579
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add fast generator for cog build #2108
Merged
Merged
Changes from all commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
ce52ff8
Add fast generator
8W9aG 3999948
Add copy weights step
8W9aG ee425a3
Add package installation step
8W9aG 98a3497
Merge branch 'main' into add-fast-generator
8W9aG 45e83d6
Add user cache to the monobase
8W9aG 0f482bf
Add rsync copy
8W9aG 23a109a
Check if weight files have changed before checksum
8W9aG 37ff311
Split install into separate steps
8W9aG 5affd00
Create requirements.txt in the build tmp directory
8W9aG 02b32b6
Merge branch 'main' into add-fast-generator
8W9aG c5377f5
Fix unit tests
8W9aG cb36e53
Fix lint
8W9aG 4bb4d24
Add basic unit tests
8W9aG 0e019cb
Use UV_CACHE_DIR and mount uv cache
8W9aG 9dbbe5a
Remove —skip-cuda from monobase build
8W9aG e006655
Fix file not found when evaluating weights
8W9aG f72607a
Add UV_LINK_MODE=copy to the uv install commands
8W9aG 339abfd
Add UV_COMPILE_BYTECODE env var
8W9aG aa106b4
Remove verbosity from monobase exec
8W9aG a42a66e
Fix integration test
8W9aG 79c0961
Switch tini and exec
8W9aG File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
package config | ||
|
||
import ( | ||
"bufio" | ||
"errors" | ||
"fmt" | ||
"os" | ||
"path/filepath" | ||
"regexp" | ||
"sort" | ||
) | ||
|
||
func GenerateRequirements(tmpDir string, config *Config) (string, error) { | ||
// Deduplicate packages between the requirements.txt and the python packages directive. | ||
packageNames := make(map[string]string) | ||
|
||
// Read the python packages configuration. | ||
for _, requirement := range config.Build.PythonPackages { | ||
packageName, err := PackageName(requirement) | ||
if err != nil { | ||
return "", err | ||
} | ||
packageNames[packageName] = requirement | ||
} | ||
|
||
// Read the python requirements. | ||
if config.Build.PythonRequirements != "" { | ||
fh, err := os.Open(config.Build.PythonRequirements) | ||
if err != nil { | ||
return "", err | ||
} | ||
scanner := bufio.NewScanner(fh) | ||
for scanner.Scan() { | ||
requirement := scanner.Text() | ||
packageName, err := PackageName(requirement) | ||
if err != nil { | ||
return "", err | ||
} | ||
packageNames[packageName] = requirement | ||
} | ||
} | ||
|
||
// If we don't have any packages skip further processing | ||
if len(packageNames) == 0 { | ||
return "", nil | ||
} | ||
|
||
// Sort the package names by alphabetical order. | ||
keys := make([]string, 0, len(packageNames)) | ||
for k := range packageNames { | ||
keys = append(keys, k) | ||
} | ||
sort.Strings(keys) | ||
|
||
// Render the expected contents | ||
requirementsContent := "" | ||
for _, k := range keys { | ||
requirementsContent += packageNames[k] + "\n" | ||
} | ||
|
||
// Check against the old requirements contents | ||
requirementsFile := filepath.Join(tmpDir, "requirements.txt") | ||
_, err := os.Stat(requirementsFile) | ||
if !errors.Is(err, os.ErrNotExist) { | ||
bytes, err := os.ReadFile(requirementsFile) | ||
if err != nil { | ||
return "", err | ||
} | ||
oldRequirementsContents := string(bytes) | ||
if oldRequirementsContents == requirementsFile { | ||
return requirementsFile, nil | ||
} | ||
} | ||
|
||
// Write out a new requirements file | ||
err = os.WriteFile(requirementsFile, []byte(requirementsContent), 0o644) | ||
if err != nil { | ||
return "", err | ||
} | ||
return requirementsFile, nil | ||
} | ||
|
||
// SplitPinnedPythonRequirement returns the name, version, findLinks, and extraIndexURLs from a requirements.txt line | ||
// in the form name==version [--find-links=<findLink>] [-f <findLink>] [--extra-index-url=<extraIndexURL>] | ||
func SplitPinnedPythonRequirement(requirement string) (name string, version string, findLinks []string, extraIndexURLs []string, err error) { | ||
pinnedPackageRe := regexp.MustCompile(`(?:([a-zA-Z0-9\-_]+)==([^ ]+)|--find-links=([^\s]+)|-f\s+([^\s]+)|--extra-index-url=([^\s]+))`) | ||
|
||
matches := pinnedPackageRe.FindAllStringSubmatch(requirement, -1) | ||
if matches == nil { | ||
return "", "", nil, nil, fmt.Errorf("Package %s is not in the expected format", requirement) | ||
} | ||
|
||
nameFound := false | ||
versionFound := false | ||
|
||
for _, match := range matches { | ||
if match[1] != "" { | ||
name = match[1] | ||
nameFound = true | ||
} | ||
|
||
if match[2] != "" { | ||
version = match[2] | ||
versionFound = true | ||
} | ||
|
||
if match[3] != "" { | ||
findLinks = append(findLinks, match[3]) | ||
} | ||
|
||
if match[4] != "" { | ||
findLinks = append(findLinks, match[4]) | ||
} | ||
|
||
if match[5] != "" { | ||
extraIndexURLs = append(extraIndexURLs, match[5]) | ||
} | ||
} | ||
|
||
if !nameFound || !versionFound { | ||
return "", "", nil, nil, fmt.Errorf("Package name or version is missing in %s", requirement) | ||
} | ||
|
||
return name, version, findLinks, extraIndexURLs, nil | ||
} | ||
|
||
func PackageName(pipRequirement string) (string, error) { | ||
name, _, _, _, err := SplitPinnedPythonRequirement(pipRequirement) | ||
return name, err | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package config | ||
|
||
import ( | ||
"path/filepath" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestGenerateRequirements(t *testing.T) { | ||
tmpDir := t.TempDir() | ||
build := Build{ | ||
PythonPackages: []string{"torch==2.5.1"}, | ||
} | ||
config := Config{ | ||
Build: &build, | ||
} | ||
requirementsFile, err := GenerateRequirements(tmpDir, &config) | ||
require.NoError(t, err) | ||
require.Equal(t, filepath.Join(tmpDir, "requirements.txt"), requirementsFile) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package dockerfile | ||
|
||
import ( | ||
"os" | ||
"path" | ||
"time" | ||
) | ||
|
||
func BuildCogTempDir(dir string) (string, error) { | ||
rootTmp := path.Join(dir, ".cog/tmp") | ||
if err := os.MkdirAll(rootTmp, 0o755); err != nil { | ||
return "", err | ||
} | ||
return rootTmp, nil | ||
} | ||
|
||
func BuildTempDir(dir string) (string, error) { | ||
rootTmp, err := BuildCogTempDir(dir) | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
if err := os.MkdirAll(rootTmp, 0o755); err != nil { | ||
return "", err | ||
} | ||
// tmpDir ends up being something like dir/.cog/tmp/build20240620123456.000000 | ||
now := time.Now().Format("20060102150405.000000") | ||
tmpDir, err := os.MkdirTemp(rootTmp, "build"+now) | ||
if err != nil { | ||
return "", err | ||
} | ||
return tmpDir, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package dockerfile | ||
|
||
import ( | ||
"path/filepath" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestBuildCogTempDir(t *testing.T) { | ||
tmpDir := t.TempDir() | ||
cogTmpDir, err := BuildCogTempDir(tmpDir) | ||
require.NoError(t, err) | ||
require.Equal(t, filepath.Join(tmpDir, ".cog/tmp"), cogTmpDir) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package dockerfile | ||
|
||
import "embed" | ||
|
||
//go:embed embed/*.whl | ||
var CogEmbed embed.FS |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just realized this. Do we still need this, now that
monobase.user
dedups the requirements and handles Torch index anyway?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeh we need to perform a dedup ourselves on the
cog.yaml
, it offers bothpython_packages
andpython_requirements
as an option.