【问题标题】:wandb: get a list of all artifact collections and all aliases of those artifactswandb:获取所有工件集合和这些工件的所有别名的列表
【发布时间】:2021-08-31 05:05:43
【问题描述】:

wandb 文档似乎没有解释如何做到这一点 - 但它应该是我想象的一个相当常见的用例?

我基本上(但不是完全)实现了我想要的,但它似乎有点笨拙?我本来希望在 ArtifactCollection 实例上有一个 self.aliases 属性?

ENTITY = os.environ.get("WANDB_ENTITY")
API_KEY = os.environ.get("WANDB_API_KEY")

def get_model_artifacts(key=None):
    wandb.login(key=key if key is not None else API_KEY)
    api = wandb.Api(overrides={"entity": ENTITY})
    model_names = [
        i
        for i in api.artifact_type(
            type_name="models", project="train"
        ).collections()
    ]
    for model in model_names:
        artifact = api.artifact("train/" + model.name + ":latest")
        model._attrs.update(artifact._attrs)
        model._attrs["metadata"] = json.loads(model._attrs["metadata"])
        model.aliases = [x["alias"] for x in model._attrs["aliases"]]
    return model_names

如果需要,我想我可能会考虑编写一个自定义的 graph-ql 查询,或者只是使用这种笨拙的方法。

我错过了什么吗?有没有更清洁的方法来做到这一点?

这个笨重的方法缺少的一件事是任何旧别名 - 它只显示最新模型,然后显示任何别名(比如说“最新”和“v4”等) - 不确定这将/应该如何被显示,但我希望能够获得旧别名(即指向旧版本工件的别名)。虽然,这不太重要。

编辑 - 在浏览了他们的 sdk 代码几个小时后,我有了这个(仍然对它的笨拙感到不满意):

ENTITY = os.environ.get("WANDB_ENTITY")
API_KEY = os.environ.get("WANDB_API_KEY")

def get_model_artifacts(key=None):
    wandb.login(key=key if key is not None else API_KEY)
    api = wandb.Api(overrides={"entity": ENTITY})
    model_artifacts = [
        a
        for a in api.artifact_type(
            type_name="models", project="train"
        ).collections()
    ]

    def get_alias_tuple(artifact_version):
        version = None
        aliases = []
        for a in artifact_version._attrs["aliases"]:
            if re.match(r"^v\d+$", a["alias"]):
                version = a["alias"]
            else:
                aliases.append(a["alias"])
        return version, aliases

    for model in model_artifacts:
        # artifact = api.artifact("train/" + model.name + ":latest")
        # model._attrs.update(artifact._attrs)
        # model._attrs["metadata"] = json.loads(model._attrs["metadata"])
        versions = model.versions()
        version_dict = dict(get_alias_tuple(version) for version in versions)
        model.version_dict = version_dict
        model.aliases = [
            x for key, val in model.version_dict.items() for x in [key] + val
        ]
    return model_artifacts

【问题讨论】:

    标签: python wandb


    【解决方案1】:

    我是安妮鲁德。我是 W&B 的一名工程师,帮助构建工件。您的解决方案非常接近,但是通过在获取工件时使用 latest 别名,我们只会考虑该工件的别名,而不是所有版本。你可以通过遍历版本来解决这个问题:

    api = wandb.Api()
    collections = [
        coll for coll in api.artifact_type(type_name=TYPE, project=PROJECT).collections()
    ]
    
    
    aliases = set()
    for coll in collections:
        for artifact in coll.versions():
            aliases.update(artifact.aliases)
    
    print(collections)
    print(aliases)
    

    目前,关于集合的文档是备用的,但我们正在公共 API 中完善它们,并将很快发布一些关于它的文档。这些 API 还没有完全准备好发布 - 所以对于粗糙的边缘表示歉意。

    如果您对工件有任何其他问题,请随时直接与我联系。总是乐于提供帮助。

    【讨论】:

    • 所以coll.versions() 调用将每 50 个版本生成 1 个 HTTP 请求(结果是分页的)。如果你想最小化这个,你可以传入per_pagecoll.versions(per_page=500))。后端将 per_page 限制限制为 500,因此您不能超过该限制。对于您的用例来说,请求的数量是否会成为问题?
    • 抱歉,我误读了您的问题。您担心对于每个集合,我们将发出单独的 coll.versions() 查询。上述 sn-p 的 HTTP 请求数最终将是 O(c + v),其中 c 是工件类型中的集合数,v 是工件类型中的版本数。实际上,v 将通过 per_page 设置进行缩放。
    • 明白了,这是有道理的!因此,对于可能有多个版本的给定模型,您需要检查别名的总列表以查看它是否具有 latestprod 以确定哪些已在生产中。我很乐意在“收藏”级别添加它以使其更容易。我们认为对于给定的模型,用户会更关心哪个特定版本被标记为 prod 之类的别名,而不是整个工件。是的,请加入我们的 Slack (wb-forum.slack.com)!请随时与我联系,我是@annirudh。
    • 看起来我们已经将我们的社区从 Slack 转移到了community.wandb.ai 的新门户——对于上面评论中的过时信息,我们深表歉意。一些好消息:我们将在下一个 CLI 版本中将 aliases 添加为集合级别的属性。别名分组将在后端完成,因此我们只需要为它们发出一个 HTTP 请求。
    • 抱歉造成混淆,我们可以互换使用 CLI 和 Python SDK 这两个术语,因为它们都在同一个代码库中。是的,此更新将传播到 SDK。
    猜你喜欢
    • 1970-01-01
    • 2023-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-18
    相关资源
    最近更新 更多