模型介绍

​ CWM(Code World Model)是 Meta 开源的一个拥有 320 亿参数的代码语言模型。它率先将“世界模型”的概念引入代码生成领域,让模型能够通过模拟代码执行过程,更深层次地理解和生成代码,而不仅仅是基于模式匹配。

​ 核心是对代码逐行执行,变量动态变化的情况。

项目链接

Github项目链接

[huggingface模型链接](facebook/cwm · Hugging Face)

modelscope模型库链接

模型简介

技术论文

个人相关模型测试


模型部署

​ meta的相关模型需要申请,可以用非国内的信息进行申请,这样会容易通过一些,或者直接在modelscope上面去下载相关模型。

modelscope下载cwm模型

命令安装 ModelScope :pip install modelscope

SDK下载:SDK (Software Development Kit)

from modelscope.hub.snapshot_download import snapshot_download
snapshot_download(
        'facebook/cwm',
        local_dir='./modelscope_cwm',
        max_workers=2,  # 防止连接超时
    )

大约10h,下载后的文件夹目录如下:

modelscope_cwm/
├── README.md                         # 模型说明文档,包含使用、安装和其他重要信息
├── config.json                       # 模型架构配置,定义了模型的结构(如层数、隐藏维度、词汇表大小等)
├── params.json                       # 存储训练超参数(如学习率、batch size、训练周期数等)的配置文件
├── tokenizer.json                    # 存储分词器的配置,包括词汇表、分词规则、特殊标记等
├── special_tokens_map.json           # 存储特殊标记的映射关系(如 [CLS]、[SEP]、[PAD] 等)
├── generation_config.json            # 与生成任务相关的配置,可能包括生成长度、温度等生成超参数
├── model-00001-of-00014.safetensors  # 模型权重文件,包含模型的一部分权重数据
├── model-00002-of-00014.safetensors  
├── model-00003-of-00014.safetensors  
├── model-00004-of-00014.safetensors  
├── model-00005-of-00014.safetensors  
├── model-00006-of-00014.safetensors  
├── model-00007-of-00014.safetensors  
├── model-00008-of-00014.safetensors  
├── model-00009-of-00014.safetensors  
├── model-00010-of-00014.safetensors  
├── model-00011-of-00014.safetensors  
├── model-00012-of-00014.safetensors  
├── model-00013-of-00014.safetensors  
├── model-00014-of-00014.safetensors  
├── model.safetensors.index.json      # 权重文件的索引文件,记录各个权重文件的加载信息
├── configuration.json                # 可能包含与特定任务或其他设置相关的配置文件
└── tokenizer_config.json             # 存储分词器的配置信息,指示分词器的行为(例如是否小写化)

修改参数,修改config.json:

 "max_position_embeddings": 131072,
  "mlp_bias": false,
  "model_type": "cwm",  # 将cwm改为llama
  "num_attention_heads": 48,
  "num_hidden_layers": 64,
  "num_key_value_heads": 8,
  "pretraining_tp": 1,
  "rms_norm_eps": 1e-05,
  "rope_scaling": {
    "factor": 16.0,
    "high_freq_factor": 4.0,
    "low_freq_factor": 1.0,
    "original_max_position_embeddings": 8192,
    "rope_type": "llama3"
  },

启动模型

​ 使用vllm推理引擎,启动模型。

CUDA_VISIBLE_DEVICES=4,7 vllm serve modelscope_cwm   --tensor-parallel-size 2   --port 8021   --max-model-len 131072   --dtype bfloat16   --trust-remote-code   --gpu-memory-utilization 0.8
  • CUDA_VISIBLE_DEVICES=4,7: 这是一个环境变量,用于指定哪些GPU设备可以被使用来进行推理工作。
  • vllm serve modelscope_cwm:启动vllm推理服务。serve指令告诉vllm启动一个推理服务器,使得它可以接受来自客户端的推理请求,并返回生成的结果。modelscope_cwm,指定要加载的模型名称或路径。modelscope_cwm可能是你在Hugging Face或其他模型库中下载的某个模型。这个名称告诉vllm加载指定的模型进行推理。
  • –tensor-parallel-size 2: 指定张量并行的规模。张量并行是一种将计算任务拆分到多个设备(如GPU)上的技术,以加速大模型的推理过程。这里的2表示模型的计算将被分配到2个设备中进行分布式推理。它有助于提升大模型在多个GPU上的执行效率,减少内存压力。
  • –port 8021:指定服务器监听的端口号。
  • –max-model-len 131072: 指定模型可以处理的最大输入长度(tokens)。
  • –dtype bfloat16:指定模型推理时使用的数据类型。bfloat16是一种16位浮动点格式,比传统的float32占用更少的内存,同时在大多数情况下能保持足够的精度。
  • –trust-remote-code: 这个参数表示信任远程代码。在下载或加载的模型中,可能包含一些自定义的代码或操作,--trust-remote-code会允许vllm执行这些代码。一般来说,只有在信任模型来源时才建议启用此选项。
  • –gpu-memory-utilization 0.8: 指定GPU内存的利用率。这里的0.8表示vllm在运行时将尽可能使用80%的GPU内存。通过合理控制内存的利用率,可以避免GPU内存过载,从而避免因OOM(内存溢出)导致的崩溃。

测试模型

问题 预期
Q1简单循环加法
Q2深度优先搜索
Q3图的路径长度

结论:对于常见的数据结构算法,均可以较好的描述出变量的变化过程,但这种描述类似于自然语言分析,与严格的debug相比,较为啰嗦,缺少固定格式,在某些步骤会有遗漏。

Q1简单循环加法

a = 3
i = 4
for n in range(i):
    a = a+1

Q2深度优先搜索

# 1. 建图(邻接表)
graph = {
    'A': ['B', 'C'],
    'B': ['A', 'D', 'E'],
    'C': ['A', 'F'],
    'D': ['B'],
    'E': ['B', 'F'],
    'F': ['C', 'E']
}

# 2. DFS 递归模板
def dfs(node, visited, graph):
    """
    深度优先搜索通用模板
    :param node:   当前访问的节点
    :param visited:已访问集合(防止回头/死循环)
    :param graph:  邻接表
    """
    if node in visited:          # 剪枝:已访问过
        return
    visited.add(node)            # 标记
    print(node, end=' ')         # 业务逻辑(这里仅打印)
    for neighbor in graph.get(node, []):
        dfs(neighbor, visited, graph)

# 3. 调用示例
visited = set()    # 这里开始
dfs('A', visited, graph)

CWMresponse:

Okay, let's see. I need to track the changes in the variables as the DFS function is called. The starting point is visited = set(), and the initial call is dfs(\"A\", visited, graph). \n\nFirst, when dfs(\"A\", visited, graph) is called, the function checks if \"A\" is in visited. Since visited is empty, it adds \"A\" to visited. Then it prints \"A\". Then it iterates over the neighbors of \"A\", which are \"B\" and \"C\". \n\nSo the first recursive call is dfs(\"B\", visited, graph). Now, inside this call, \"B\" is not in visited, so it's added. Then \"B\" is printed. The neighbors of \"B\" are \"A\", \"D\", \"E\". \n\nBut when it calls dfs(\"A\", visited, graph) again, \"A\" is already in visited, so it returns immediately. Then it moves to \"D\". \"D\" is not in visited, so it's added and printed. The neighbors of \"D\" are just \"B\", which is already visited, so that call returns. Then back to \"B\"'s loop, next neighbor is \"E\". \n\n\"E\" is not in visited, so it's added and printed. Neighbors of \"E\" are \"B\" and \"F\". \"B\" is already visited, so it calls dfs(\"F\", visited, graph). \n\nNow, \"F\" is not in visited, so it's added and printed. Neighbors of \"F\" are \"C\" and \"E\". \"E\" is already visited, so it calls dfs(\"C\", visited, graph). \n\nWait, but \"C\" was a neighbor of \"A\" in the original call. But since we're in the \"F\" branch now, does that mean \"C\" hasn't been visited yet? Let me check. \n\nWait, the original call to \"A\" had neighbors \"B\" and \"C\". After processing \"B\" and its subtree (which includes \"D\", \"E\", \"F\"), the loop in \"A\" would then process \"C\". But in this case, when we're in the \"F\" branch, which is part of the \"E\" branch, which is part of the \"B\" branch, which is part of the \"A\" branch. So when we get to \"F\", we call dfs(\"C\", ...). But \"C\" hasn't been visited yet because the original \"A\" call's loop is still waiting to process \"C\" after \"B\" is done. Wait, no. Because in the initial call to \"A\", after adding \"A\" to visited, it starts looping through \"B\" and \"C\". It first calls dfs(\"B\", ...), which processes the entire subtree under \"B\", including \"D\", \"E\", \"F\". Then, when that returns, the loop in \"A\" continues to the next neighbor, which is \"C\". \n\nWait, but in the current path, when we're in \"F\", we call dfs(\"C\", ...). But \"C\" hasn't been visited yet. So that would add \"C\" to visited and print it. Then \"C\"'s neighbors are \"A\" and \"F\". \"A\" is already visited, \"F\" is already visited (since we just came from \"F\"). So that call returns. Then back to \"F\"'s loop, which has no more neighbors. Then back to \"E\"'s loop, which had \"F\" and then done. Then back to \"B\"'s loop, which had \"E\" and done. Then back to \"A\"'s loop, which had \"B\" and now moves to \"C\". But wait, \"C\" was already visited when we called dfs(\"C\", ...) from \"F\"? Or is that a different path?\n\nWait, no. Because in the initial call to \"A\", after processing \"B\" and its entire subtree (which includes \"E\" and \"F\"), the loop in \"A\" would then process \"C\". But in the path we're taking now, when we're in \"F\", we call dfs(\"C\", ...). So \"C\" is added to visited there. Then, when the original \"A\" loop gets to \"C\", it would check if \"C\" is in visited (which it is), so it skips it. \n\nWait, but that would mean that \"C\" is visited twice: once through the \"F\" -> \"C\" path, and once through the \"A\" -> \"C\" path. But in reality, the DFS should visit each node only once. So maybe my initial understanding is wrong. \n\nWait, let's step through the code carefully. \n\nStarting with visited = set(). \n\nCall dfs(\"A\", visited, graph). \n\nInside dfs(\"A\", ...): \n- \"A\" not in visited, add it. visited is now {\"A\"}.\n- Print \"A\".\n- Neighbors are \"B\", \"C\".\n\nFirst neighbor is \"B\". Call dfs(\"B\", visited, graph). \n\nInside dfs(\"B\", ...): \n- \"B\" not in visited, add it. visited is {\"A\", \"B\"}.\n- Print \"B\".\n- Neighbors are \"A\", \"D\", \"E\".\n\nFirst neighbor is \"A\". Call dfs(\"A\", visited, graph). \n\nInside dfs(\"A\", ...): \n- \"A\" is in visited, return. \n\nBack to \"B\"'s loop. Next neighbor is \"D\". Call dfs(\"D\", visited, graph). \n\nInside dfs(\"D\", ...): \n- \"D\" not in visited, add it. visited is {\"A\", \"B\", \"D\"}.\n- Print \"D\".\n- Neighbors are \"B\". \n\nCall dfs(\"B\", visited, graph). \n\nInside dfs(\"B\", ...): \n- \"B\" is in visited, return. \n\nBack to \"D\"'s loop. No more neighbors. Return. \n\nBack to \"B\"'s loop. Next neighbor is \"E\". Call dfs(\"E\", visited, graph). \n\nInside dfs(\"E\", ...): \n- \"E\" not in visited, add it. visited is {\"A\", \"B\", \"D\", \"E\"}.\n- Print \"E\".\n- Neighbors are \"B\", \"F\".\n\nFirst neighbor is \"B\". Call dfs(\"B\", visited, graph). \n\nInside dfs(\"B\", ...): \n- \"B\" is in visited, return. \n\nBack to \"E\"'s loop. Next neighbor is \"F\". Call dfs(\"F\", visited, graph). \n\nInside dfs(\"F\", ...): \n- \"F\" not in visited, add it. visited is {\"A\", \"B\", \"D\", \"E\", \"F\"}.\n- Print \"F\".\n- Neighbors are \"C\", \"E\".\n\nFirst neighbor is \"C\". Call dfs(\"C\", visited, graph). \n\nInside dfs(\"C\", ...): \n- \"C\" not in visited, add it. visited is {\"A\", \"B\", \"D\", \"E\", \"F\", \"C\"}.\n- Print \"C\".\n- Neighbors are \"A\", \"F\".\n\nFirst neighbor is \"A\". Call dfs(\"A\", visited, graph). \n\nInside dfs(\"A\", ...): \n- \"A\" is in visited, return. \n\nBack to \"C\"'s loop. Next neighbor is \"F\". Call dfs(\"F\", visited, graph). \n\nInside dfs(\"F\", ...): \n- \"F\" is in visited, return. \n\nBack to \"C\"'s loop. No more neighbors. Return. \n\nBack to \"F\"'s loop. Next neighbor is \"E\". Call dfs(\"E\", visited, graph). \n\nInside dfs(\"E\", ...): \n- \"E\" is in visited, return. \n\nBack to \"F\"'s loop. No more neighbors. Return. \n\nBack to \"E\"'s loop. No more neighbors. Return. \n\nBack to \"B\"'s loop. No more neighbors. Return. \n\nBack to \"A\"'s loop. Next neighbor is \"C\". Call dfs(\"C\", visited, graph). \n\nInside dfs(\"C\", ...): \n- \"C\" is in visited (added earlier when called from \"F\"), so return. \n\nBack to \"A\"'s loop. No more neighbors. Return. \n\nSo the order of printing is A B D E F C. \n\nWait, but when we called dfs(\"C\", ...) from \"F\", \"C\" was added to visited. Then, when the original \"A\" loop gets to \"C\", it's already visited, so it skips. \n\nSo the visited set ends up as {\"A\", \"B\", \"D\", \"E\", \"F\", \"C\"}. \n\nBut let me check the print order. The print statements are in the order the nodes are visited. So the output should be A B D E F C. \n\nBut wait, when we process \"F\", we call dfs(\"C\", ...), which prints \"C\". Then, when we return to \"A\"'s loop, \"C\" is already visited, so it's skipped. \n\nSo the final visited set is all six nodes, and the print order is A B D E F C. \n\nBut let me confirm by simulating each step with the variables. \n\nStarting with visited = set(). \n\nCall dfs(\"A\", visited, graph). \n\n- node = \"A\", visited = set(). \n- \"A\" not in visited. Add \"A\" to visited. Now visited = {\"A\"}.\n- Print \"A\".\n- Neighbors: \"B\", \"C\".\n\nFirst neighbor \"B\": call dfs(\"B\", visited, graph). \n\n- node = \"B\", visited = {\"A\"}.\n- \"B\" not in visited. Add \"B\". visited = {\"A\", \"B\"}.\n- Print \"B\".\n- Neighbors: \"A\", \"D\", \"E\".\n\nFirst neighbor \"A\": call dfs(\"A\", visited, graph). \n\n- node = \"A\", visited = {\"A\", \"B\"}.\n- \"A\" is in visited. Return.\n\nBack to \"B\"'s loop. Next neighbor \"D\": call dfs(\"D\", visited, graph). \n\n- node = \"D\", visited = {\"A\", \"B\"}.\n- \"D\" not in visited. Add \"D\". visited = {\"A\", \"B\", \"D\"}.\n- Print \"D\".\n- Neighbors: \"B\".\n\nCall dfs(\"B\", visited, graph). \n\n- node = \"B\", visited = {\"A\", \"B\", \"D\"}.\n- \"B\" is in visited. Return.\n\nBack to \"D\"'s loop. No more neighbors. Return.\n\nBack to \"B\"'s loop. Next neighbor \"E\": call dfs(\"E\", visited, graph). \n\n- node = \"E\", visited = {\"A\", \"B\", \"D\"}.\n- \"E\" not in visited. Add \"E\". visited = {\"A\", \"B\", \"D\", \"E\"}.\n- Print \"E\".\n- Neighbors: \"B\", \"F\".\n\nFirst neighbor \"B\": call dfs(\"B\", visited, graph). \n\n- node = \"B\", visited = {\"A\", \"B\", \"D\", \"E\"}.\n- \"B\" is in visited. Return.\n\nBack to \"E\"'s loop. Next neighbor \"F\": call dfs(\"F\", visited, graph). \n\n- node = \"F\", visited = {\"A\", \"B\", \"D\", \"E\"}.\n- \"F\" not in visited. Add \"F\". visited = {\"A\", \"B\", \"D\", \"E\", \"F\"}.\n- Print \"F\".\n- Neighbors: \"C\", \"E\".\n\nFirst neighbor \"C\": call dfs(\"C\", visited, graph). \n\n- node = \"C\", visited = {\"A\", \"B\", \"D\", \"E\", \"F\"}.\n- \"C\" not in visited. Add \"C\". visited = {\"A\", \"B\", \"D\", \"E\", \"F\", \"C\"}.\n- Print \"C\".\n- Neighbors: \"A\", \"F\".\n\nFirst neighbor \"A\": call dfs(\"A\", visited, graph). \n\n- node = \"A\", visited = {\"A\", \"B\", \"D\", \"E\", \"F\", \"C\"}.\n- \"A\" is in visited. Return.\n\nBack to \"C\"'s loop. Next neighbor \"F\": call dfs(\"F\", visited, graph). \n\n- node = \"F\", visited = {\"A\", \"B\", \"D\", \"E\", \"F\", \"C\"}.\n- \"F\" is in visited. Return.\n\nBack to \"C\"'s loop. No more neighbors. Return.\n\nBack to \"F\"'s loop. Next neighbor \"E\": call dfs(\"E\", visited, graph). \n\n- node = \"E\", visited = {\"A\", \"B\", \"D\", \"E\", \"F\", \"C\"}.\n- \"E\" is in visited. Return.\n\nBack to \"F\"'s loop. No more neighbors. Return.\n\nBack to \"E\"'s loop. No more neighbors. Return.\n\nBack to \"B\"'s loop. No more neighbors. Return.\n\nBack to \"A\"'s loop. Next neighbor \"C\": call dfs(\"C\", visited, graph). \n\n- node = \"C\", visited = {\"A\", \"B\", \"D\", \"E\", \"F\", \"C\"}.\n- \"C\" is in visited. Return.\n\nBack to \"A\"'s loop. No more neighbors. Return.\n\nSo the final visited set is {\"A\", \"B\", \"C\", \"D\", \"E\", \"F\"}, and the print order is A B D E F C. \n\nWait, but when we printed \"C\" from the \"F\" branch, then when we get back to \"A\"'s loop, \"C\" is already visited, so it's skipped. \n\nSo the output is A B D E F C. \n\nBut let me check the order again. The print statements are executed in the order the nodes are visited. So the sequence is:\n\nA (from initial call)\nB (from A's neighbor)\nD (from B's neighbor)\nE (from B's neighbor)\nF (from E's neighbor)\nC (from F's neighbor)\n\nYes, that's the order. \n\nSo the visited set starts as empty, then becomes {\"A\"}, then {\"A\", \"B\"}, then {\"A\", \"B\", \"D\"}, then {\"A\", \"B\", \"D\", \"E\"}, then {\"A\", \"B\", \"D\", \"E\", \"F\"}, then {\"A\", \"B\", \"D\", \"E\", \"F\", \"C\"}. \n\nEach step, the visited set grows by one element as each node is visited for the first time. \n\nSo the dynamic changes are:\n\nvisited = set() → {\"A\"} → {\"A\", \"B\"} → {\"A\", \"B\", \"D\"} → {\"A\", \"B\", \"D\", \"E\"} → {\"A\", \"B\", \"D\", \"E\", \"F\"}"

Q3图的路径长度

from typing import Dict, List, Tuple, Optional

# 1. 带权有向图(邻接表:{from: [(to, weight), ...]})
graph: Dict[str, List[Tuple[str, int]]] = {
    'A': [('B', 2), ('C', 5)],
    'B': [('C', 1), ('D', 3)],
    'C': [('D', 1), ('E', 4)],
    'D': [('E', 1), ('F', 6)],
    'E': [('F', 2)],
    'F': []          # 汇点
}

# 2. 全局变量,用于收集所有从 start 到 end 的路径及总权重
all_paths: List[Tuple[List[str], int]] = []

def dfs_all_paths(
        node: str,
        target: str,
        visited: set,
        path: List[str],
        total_weight: int) -> None:
    """
    递归 DFS:枚举从 node 到 target 的所有路径,并记录总权重
    带环检测(visited)
    """
    # 2.1 访问标记(防止重复走同一个节点形成环)
    visited.add(node)
    path.append(node)

    # 2.2 到达终点 → 记录当前路径及权重
    if node == target:
        all_paths.append((path.copy(), total_weight))
    else:
        # 2.3 遍历所有后继边
        for neighbor, w in graph.get(node, []):
            if neighbor not in visited:          # 环检测
                dfs_all_paths(
                    neighbor,
                    target,
                    visited,
                    path,
                    total_weight + w
                )

    # 2.4 回溯:撤销选择
    path.pop()
    visited.remove(node)

# 3. 调用示例:找出 A → F 的所有路径
dfs_all_paths('A', 'F', set(), [], 0) # 这里开始

# 4. 结果展示
print('所有 A→F 的路径及总权重:')
for p, w in all_paths:
    print(f"{' -> '.join(p)}  |  总权重 = {w}"

CWMresponse:

"Okay, let's see. I need to track the variables step by step as the code runs. The code is a DFS that finds all paths from node \"A\" to \"F\" in a weighted directed graph. The function `dfs_all_paths` is recursive, so I should follow each recursive call and see how the variables change.\n\nFirst, the initial call is `dfs_all_paths(\"A\", \"F\", set(), [], 0, all_paths)`. At this point, `all_paths` is an empty list. Let me note that down.\n\nWhen the function starts, `node` is \"A\", `target` is \"F\", `visited` is an empty set, `path` is an empty list, `total_weight` is 0, and `all_paths` is still empty.\n\nSince \"A\" is not in `visited`, we add it to `visited` and append it to `path`. Now, `visited` is {\"A\"}, `path` is [\"A\"], and `total_weight` remains 0.\n\nNext, we check if \"A\" is the target \"F\". It's not, so we loop through its neighbors: \"B\" with weight 2 and \"C\" with weight 5.\n\nFirst neighbor is \"B\". Since \"B\" is not in `visited`, we call `dfs_all_paths(\"B\", \"F\", {\"A\"}, [\"A\"], 2, all_paths)`.\n\nIn this new call, `node` is \"B\", `visited` is {\"A\"}, `path` is [\"A\"], `total_weight` is 2. Again, \"B\" is not visited, so add to `visited` (now {\"A\", \"B\"}), append to `path` ([\"A\", \"B\"]).\n\nCheck if \"B\" is target? No. Neighbors are \"C\" (1) and \"D\" (3).\n\nFirst neighbor \"C\": not visited. Call `dfs_all_paths(\"C\", \"F\", {\"A\", \"B\"}, [\"A\", \"B\"], 3, all_paths)`.\n\nIn this call, `node` is \"C\", `visited` is {\"A\", \"B\"}, `path` is [\"A\", \"B\"], `total_weight` is 3. Add \"C\" to visited (now {\"A\", \"B\", \"C\"}), path becomes [\"A\", \"B\", \"C\"].\n\nCheck if \"C\" is target? No. Neighbors are \"D\" (1) and \"E\" (4).\n\nFirst neighbor \"D\": not visited. Call `dfs_all_paths(\"D\", \"F\", {\"A\", \"B\", \"C\"}, [\"A\", \"B\", \"C\"], 4, all_paths)`.\n\nNow, `node` is \"D\", `visited` is {\"A\", \"B\", \"C\"}, `path` is [\"A\", \"B\", \"C\"], `total_weight` is 4. Add \"D\" to visited (now {\"A\", \"B\", \"C\", \"D\"}), path becomes [\"A\", \"B\", \"C\", \"D\"].\n\nCheck if \"D\" is target? No. Neighbors are \"E\" (1) and \"F\" (6).\n\nFirst neighbor \"E\": not visited. Call `dfs_all_paths(\"E\", \"F\", {\"A\", \"B\", \"C\", \"D\"}, [\"A\", \"B\", \"C\", \"D\"], 5, all_paths)`.\n\nIn this call, `node` is \"E\", `visited` is {\"A\", \"B\", \"C\", \"D\"}, `path` is [\"A\", \"B\", \"C\", \"D\"], `total_weight` is 5. Add \"E\" to visited (now {\"A\", \"B\", \"C\", \"D\", \"E\"}), path becomes [\"A\", \"B\", \"C\", \"D\", \"E\"].\n\nCheck if \"E\" is target? No. Neighbor is \"F\" (2). Not visited. Call `dfs_all_paths(\"F\", \"F\", {\"A\", \"B\", \"C\", \"D\", \"E\"}, [\"A\", \"B\", \"C\", \"D\", \"E\"], 7, all_paths)`.\n\nNow, `node` is \"F\", which is the target. So we append the path and total weight to `all_paths`. `all_paths` now has one entry: ([\"A\", \"B\", \"C\", \"D\", \"E\", \"F\"], 7). Then, backtrack: remove \"F\" from path and visited.\n\nBack to \"E\" call. After returning, path is [\"A\", \"B\", \"C\", \"D\", \"E\"], visited is {\"A\", \"B\", \"C\", \"D\", \"E\"}. No more neighbors, so pop \"E\" from path and remove from visited. Now path is [\"A\", \"B\", \"C\", \"D\"], visited is {\"A\", \"B\", \"C\", \"D\"}.\n\nBack to \"D\" call. Next neighbor is \"F\" (6). Not visited. Call `dfs_all_paths(\"F\", \"F\", {\"A\", \"B\", \"C\", \"D\"}, [\"A\", \"B\", \"C\", \"D\"], 10, all_paths)`.\n\nNow, `node` is \"F\", target. Append ([\"A\", \"B\", \"C\", \"D\", \"F\"], 10) to `all_paths`. Now `all_paths` has two entries. Backtrack: remove \"F\" from path and visited.\n\nBack to \"D\" call. No more neighbors. Pop \"D\" from path, remove from visited. Path is [\"A\", \"B\", \"C\"], visited is {\"A\", \"B\", \"C\"}.\n\nBack to \"C\" call. Next neighbor is \"E\" (4). Not visited. Call `dfs_all_paths(\"E\", \"F\", {\"A\", \"B\", \"C\"}, [\"A\", \"B\", \"C\"], 7, all_paths)`.\n\nIn this call, `node` is \"E\", `visited` is {\"A\", \"B\", \"C\"}, `path` is [\"A\", \"B\", \"C\"], `total_weight` is 7. Add \"E\" to visited (now {\"A\", \"B\", \"C\", \"E\"}), path becomes [\"A\", \"B\", \"C\", \"E\"].\n\nCheck if \"E\" is target? No. Neighbor is \"F\" (2). Not visited. Call `dfs_all_paths(\"F\", \"F\", {\"A\", \"B\", \"C\", \"E\"}, [\"A\", \"B\", \"C\", \"E\"], 9, all_paths)`.\n\nAppend ([\"A\", \"B\", \"C\", \"E\", \"F\"], 9) to `all_paths`. Now three entries. Backtrack.\n\nBack to \"E\" call. Pop \"E\", remove from visited. Path is [\"A\", \"B\", \"C\"], visited is {\"A\", \"B\", \"C\"}.\n\nBack to \"C\" call. No more neighbors. Pop \"C\", remove from visited. Path is [\"A\", \"B\"], visited is {\"A\", \"B\"}.\n\nBack to \"B\" call. Next neighbor is \"D\" (3). Not visited. Call `dfs_all_paths(\"D\", \"F\", {\"A\", \"B\"}, [\"A\", \"B\"], 5, all_paths)`.\n\nIn this call, `node` is \"D\", `visited` is {\"A\", \"B\"}, `path` is [\"A\", \"B\"], `total_weight` is 5. Add \"D\" to visited (now {\"A\", \"B\", \"D\"}), path becomes [\"A\", \"B\", \"D\"].\n\nCheck if \"D\" is target? No. Neighbors are \"E\" (1) and \"F\" (6).\n\nFirst neighbor \"E\": not visited. Call `dfs_all_paths(\"E\", \"F\", {\"A\", \"B\", \"D\"}, [\"A\", \"B\", \"D\"], 6, all_paths)`.\n\nIn this call, `node` is \"E\", `visited` is {\"A\", \"B\", \"D\"}, `path` is [\"A\", \"B\", \"D\"], `total_weight` is 6. Add \"E\" to visited (now {\"A\", \"B\", \"D\", \"E\"}), path becomes [\"A\", \"B\", \"D\", \"E\"].\n\nCheck if \"E\" is target? No. Neighbor is \"F\" (2). Not visited. Call `dfs_all_paths(\"F\", \"F\", {\"A\", \"B\", \"D\", \"E\"}, [\"A\", \"B\", \"D\", \"E\"], 8, all_paths)`.\n\nAppend ([\"A\", \"B\", \"D\", \"E\", \"F\"], 8) to `all_paths`. Now four entries. Backtrack.\n\nBack to \"E\" call. Pop \"E\", remove from visited. Path is [\"A\", \"B\", \"D\"], visited is {\"A\", \"B\", \"D\"}.\n\nBack to \"D\" call. Next neighbor is \"F\" (6). Not visited. Call `dfs_all_paths(\"F\", \"F\", {\"A\", \"B\", \"D\"}, [\"A\", \"B\", \"D\"], 11, all_paths)`.\n\nAppend ([\"A\", \"B\", \"D\", \"F\"], 11) to `all_paths`. Now five entries. Backtrack.\n\nBack to \"D\" call. Pop \"D\", remove from visited. Path is [\"A\", \"B\"], visited is {\"A\", \"B\"}.\n\nBack to \"B\" call. No more neighbors. Pop \"B\", remove from visited. Path is [\"A\"], visited is {\"A\"}.\n\nBack to initial call. Next neighbor is \"C\" (5). Not visited. Call `dfs_all_paths(\"C\", \"F\", {\"A\"}, [\"A\"], 5, all_paths)`.\n\nIn this call, `node` is \"C\", `visited` is {\"A\"}, `path` is [\"A\"], `total_weight` is 5. Add \"C\" to visited (now {\"A\", \"C\"}), path becomes [\"A\", \"C\"].\n\nCheck if \"C\" is target? No. Neighbors are \"D\" (1) and \"E\" (4).\n\nFirst neighbor \"D\": not visited. Call `dfs_all_paths(\"D\", \"F\", {\"A\", \"C\"}, [\"A\", \"C\"], 6, all_paths)`.\n\nIn this call, `node` is \"D\", `visited` is {\"A\", \"C\"}, `path` is [\"A\", \"C\"], `total_weight` is 6. Add \"D\" to visited (now {\"A\", \"C\", \"D\"}), path becomes [\"A\", \"C\", \"D\"].\n\nCheck if \"D\" is target? No. Neighbors are \"E\" (1) and \"F\" (6).\n\nFirst neighbor \"E\": not visited. Call `dfs_all_paths(\"E\", \"F\", {\"A\", \"C\", \"D\"}, [\"A\", \"C\", \"D\"], 7, all_paths)`.\n\nIn this call, `node` is \"E\", `visited` is {\"A\", \"C\", \"D\"}, `path` is [\"A\", \"C\", \"D\"], `total_weight` is 7. Add \"E\" to visited (now {\"A\", \"C\", \"D\", \"E\"}), path becomes [\"A\", \"C\", \"D\", \"E\"].\n\nCheck if \"E\" is target? No. Neighbor is \"F\" (2). Not visited. Call `dfs_all_paths(\"F\", \"F\", {\"A\", \"C\", \"D\", \"E\"}, [\"A\", \"C\", \"D\", \"E\"], 9, all_paths)`.\n\nAppend ([\"A\", \"C\", \"D\", \"E\", \"F\"], 9) to `all_paths`. Now six entries. Backtrack.\n\nBack to \"E\" call. Pop \"E\", remove from visited. Path is [\"A\", \"C\", \"D\"], visited is {\"A\", \"C\", \"D\"}.\n\nBack to \"D\" call. Next neighbor is \"F\" (6). Not visited. Call `dfs_all_paths(\"F\", \"F\", {\"A\", \"C\", \"D\"}, [\"A\", \"C\", \"D\"], 12, all_paths)`.\n\nAppend ([\"A\", \"C\", \"D\", \"F\"], 12) to `all_paths`. Now seven entries. Backtrack.\n\nBack to \"D\" call. Pop \"D\", remove from visited. Path is [\"A\", \"C\"], visited is {\"A\", \"C\"}.\n\nBack to \"C\" call. Next neighbor is \"E\" (4). Not visited. Call `dfs_all_paths(\"E\", \"F\", {\"A\", \"C\"}, [\"A\", \"C\"], 9, all_paths)`.\n\nIn this call, `node` is \"E\", `visited` is {\"A\", \"C\"}, `path` is [\"A\", \"C\"], `total_weight` is 9. Add \"E\" to visited (now {\"A\", \"C\", \"E\"}), path becomes [\"A\", \"C\", \"E\"].\n\nCheck if \"E\" is target? No. Neighbor is \"F\" (2). Not visited. Call `dfs_all_paths(\"F\", \"F\", {\"A\", \"C\", \"E\"}, [\"A\", \"C\", \"E\"], 11, all_paths)`.\n\nAppend ([\"A\", \"C\", \"E\", \"F\"], 11) to `all_paths`. Now eight entries. Backtrack.\n\nBack to \"E\" call. Pop \"E\", remove from visited. Path is [\"A\", \"C\"], visited is {\"A\", \"C\"}.\n\nBack to \"C\" call. No more neighbors. Pop \"C\", remove from visited. Path is [\"A\"], visited is {\"A\"}.\n\nBack to initial call. No more neighbors. Pop \"A\", remove from visited. Path is empty, visited is empty.\n\nFinally, the function returns. `all_paths` now has eight entries.\n</think>\n\nHere's the step-by-step variable changes:\n\n1. `all_paths = []` (initial state)\n2. After first path found: `all_paths = [([\"A\", \"B\", \"C\", \"D\", \"E\", \"F\"], 7)]`\n3. After second path: `all_paths = [([\"A\", \"B\", \"C\", \"D\", \"E\", \"F\"], 7), ([\"A\", \"B\", \"C\", \"D\", \"F\"], 10)]`\n4. After third path: `all_paths = [([\"A\", \"B\", \"C\", \"D\", \"E\", \"F\"], 7), ([\"A\", \"B\", \"C\", \"D\", \"F\"], 10), ([\"A\", \"B\", \"C\", \"E\", \"F\"], 9)]`\n5. After fourth path: `all_paths = [([\"A\", \"B\",",...

常见问题

Q1:huggingface与github的区别?为什么要先GitHub然后再huggingface?

Q2:micromamba、ev、conda三者的区别(还有pip)?

# 1. 装 micromamba(比 conda 轻量,国内源也快)
wget https://github.com/mamba-org/micromamba-releases/releases/latest/download/micromamba-linux-64 -O micromamba

./micromamba shell init --shell=bash --root-prefix=~/micromamb
source ~/.bashrc

# 2. 拉官方仓库(国内镜像已写进依赖)
git clone https://github.com/meta-cwm/cwm.git # 里面含有模型运行时的一些配置文件
cd cwm
# 创建新环境
micromamba create -n cwm2 python=3.11 -c conda-forge -y
micromamba activate cwm2
# 安装yaml环境的包
micromamba install --yes --file environment.yaml  
# 安装pip的包
pip install -r requirements.txt

Q3:D:\A学习资料\D读研\人类基准测试>scp “D:\A学习资料\D读研\人类基准测试\cwm-main.zip” xiaoyao@172.16.11.106:~/workspace/CWM_4bit/
ssh: connect to host 172.16.11.106 port 22: Connection timed out
scp: Connection closed 如何直接传zip?

Q4:一个完整的基础流程要背熟。

torchrun –nproc-per-node 2 -m serve.fgserve config=serve/configs/cwm.ya
ml checkpoint_dir=./modelscope_cwm

这个可以!

先修改一个备份文件,

Q4.hugging face 与github的关系,及模型的部署。

cwm 改为llama,才可以推理。为什么?

Q5: 如何启动?

(myenv_cwm02) xiaoyao@ec07b5717b19:~/workspace/cwm/CWM$ CUDA_VISIBLE_DEVICES=4,7 vllm serve modelscope_cwm   --tensor-parallel-size 2   --port 8021   --max-model-len 131072   --dtype bfloat16   --trust-remote-code   --gpu-memory-utilization 0.8

如何查询?

curl http://localhost:8021/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "modelscope_cwm",
    "messages": [
      {"role": "system", "content": "You are a helpful AI assistant. You always reason before responding, using the following format:<think>your internal reasoning</think>your external response"},
      {"role": "user", "content": "[代码块],从[ ]开始,逐行输出变量动态变化过程。"}
    ],
    "max_tokens": 3200,
    "temperature": 0
  }'
  
  
curl http://localhost:8021/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "modelscope_cwm",
    "messages": [
      {"role": "system", "content": "You are a helpful AI assistant. You always reason before responding, using the following format:<think>your internal reasoning</think>your external response"},
      {"role": "user", "content": "Problem Description: \n 
You have n tasks to complete each day. Every task i has: \n 
A deadline dᵢ (in hours, counted from 00:00), \n 
A duration tᵢ (hours needed to finish the task), \n 
A penalty pᵢ (penalty incurred for each hour the task remains unfinished past its deadline). \n 
You may start any task at any moment of the day, but once started it must run uninterrupted. If a task finishes after its deadline, you pay pᵢ per hour of delay.
Your goal is to order the tasks so that the total penalty (sum of all delay penalties) is minimized. \n 
Input Format: \n 
First line: one integer n (1 ≤ n ≤ 100), the number of tasks. \n 
Next n lines: three integers dᵢ, tᵢ, pᵢ (1 ≤ dᵢ ≤ 24, 1 ≤ tᵢ ≤ 24, 1 ≤ pᵢ ≤ 100), giving deadline, duration, and penalty for task i.
Output Format:
A single integer: the minimum achievable total penalty."}
    ],
    "max_tokens": 3200,
    "temperature": 0
  }'

Q6:步骤?

下模型+改参数,直接用vllm进行推进。 param中的推理,cwm改为llama

curl http://localhost:8021/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "modelscope_cwm",
    "messages": [
      {
        "role": "system",
        "content": "You are a helpful AI assistant. You always reason before responding, using the following format:\n\n<think>\nyour internal reasoning\n</think>\nyour external response"
      },
      {
        "role": "user",
        "content": "Problem Description:\nYou have n tasks to complete each day. Every task i has:\n- A deadline dᵢ (in hours, counted from 00:00),\n- A duration tᵢ (hours needed to finish the task),\n- A penalty pᵢ (penalty incurred for each hour the task remains unfinished past its deadline).\nYou may start any task at any moment of the day, but once started it must run uninterrupted. If a task finishes after its deadline, you pay pᵢ per hour of delay.\nYour goal is to order the tasks so that the total penalty (sum of all delay penalties) is minimized.\n\nInput Format:\nFirst line: one integer n (1 ≤ n ≤ 100), the number of tasks.\nNext n lines: three integers dᵢ, tᵢ, pᵢ (1 ≤ dᵢ ≤ 24, 1 ≤ tᵢ ≤ 24, 1 ≤ pᵢ ≤ 100), giving deadline, duration, and penalty for task i.\n\nOutput Format:\nA single integer: the minimum achievable total penalty.\n\nWrite a program to answer the above questions."
      }
    ],
    "max_tokens": 13200,
    "temperature": 0
  }'

Q5:SDK与命令行下载有什么区别?

  • SDK:是一组开发工具、库、API 和文档,供开发者用于构建应用程序或服务。可把它理解为资源集成库,提供程序接口与工具获取外部资源。(包括下载模型、加载和使用预训练模型等)
  • 命令行下载:适合快速和灵活的单次下载任务,不涉及其他操作。

Q6:分析一下vllm的作用?

​ 可以将vllm理解为一种启动框架,但它不仅仅是一个简单的“启动”工具。它更像是一个高效的推理引擎,负责管理和优化大规模语言模型的加载与推理过程。具体来说,vllm具备以下功能,因此它的作用比单纯的“启动”还要复杂和重要:

  1. 模型加载与管理

vllm能够从Hugging Face等平台加载预训练模型,并负责模型的存储和管理。它支持在内存中高效地加载和使用大型模型,减少加载时间和内存占用。

  1. 推理优化

vllm针对大规模语言模型进行了推理效率的优化。它能够自动分配计算资源,优化内存使用,并加速推理过程,尤其是在分布式或多GPU环境下。这样,vllm不仅是启动模型,更能提升模型推理的速度和效率。

  1. 并行化和分布式推理

对于非常大的语言模型,vllm支持并行计算,可以在多个GPU甚至多个机器上分布式运行。这使得它不仅仅是一个启动工具,它是一个可以高效管理和执行推理任务的框架。

  1. 内存优化

vllm针对模型推理过程中可能出现的内存瓶颈进行优化,使用诸如内存缓存、分层推理等技术,减少了高内存消耗和重复计算的情况,从而提高了推理的可扩展性和性能。

  1. API与管理接口

vllm提供了一组简单的API,使得开发者能够更轻松地启动、管理和运行模型推理任务。它抽象了很多复杂的底层细节,让使用者专注于业务逻辑,而不是处理资源分配或优化问题。

Q7: GitHub仓库中的服务,checkpoint与safetensor格式的区别?模型之间是否有差异?为什么github仓库会有额外的服务。

Q8: huggingface申请失败后怎么办?

  1. huggingface 仓库申请权限失败 (换 modelscope) - Cold_Chair - 博客园

  2. 用国外的信息进行申请。


发文章找实习