当前位置:   article > 正文

开源模型应用落地-CodeQwen模型小试-探索更多使用场景(三)

开源模型应用落地-CodeQwen模型小试-探索更多使用场景(三)

一、前言

    代码专家模型是基于人工智能的先进技术,它能够自动分析和理解大量的代码库,并从中学习常见的编码模式和最佳实践。这种模型可以提供准确而高效的代码建议,帮助开发人员在编写代码时避免常见的错误和陷阱。

    通过学习代码专家模型,开发人员可以获得高效、准确和个性化的代码支持。这不仅可以提高工作效率,还可以在不同的技术环境中简化软件开发工作流程。代码专家模型的引入将为开发人员带来更多的机会去关注创造性的编程任务,从而推动软件开发的创新和进步。

    开源模型应用落地-CodeQwen模型小试-小试牛刀(一)

    开源模型应用落地-CodeQwen模型小试-SQL专家测试(二)


二、术语

2.1.CodeQwen1.5

    基于 Qwen 语言模型初始化,拥有 7B 参数的模型,其拥有 GQA 架构,经过了 ~3T tokens 代码相关的数据进行预训练,共计支持 92 种编程语言、且最长支持 64K 的上下文输入。效果方面,CodeQwen1.5 展现出了非凡的代码生成、长序列建模、代码修改、SQL 能力等,该模型可以大大提高开发人员的工作效率,并在不同的技术环境中简化软件开发工作流程。

CodeQwen 是基础的 Coder

    代码生成是大语言模型的关键能力之一,期待模型将自然语言指令转换为具有精确的、可执行的代码。仅拥有 70 亿参数的 CodeQwen1.5 在基础代码生成能力上已经超过了更尺寸的模型,进一步缩小了开源 CodeLLM 和 GPT-4 之间编码能力的差距。

CodeQwen 是长序列 Coder

    长序列能力对于代码模型来说至关重要,是理解仓库级别代码、成为 Code Agent 的核心能力。而当前的代码模型对于长度的支持仍然非常有限,阻碍了其实际应用的潜力。CodeQwen1.5 希望进一步推进开源代码模型在长序列建模上的进展,我们收集并构造了仓库级别的长序列代码数据进行预训练,通过精细的数据配比和组织方式,使其最终可以最长支持 64K 的输入长度。

CodeQwen 是优秀的代码修改者

    一个好的代码助手不仅可以根据指令生成代码,还能够针对已有代码或者新的需求进行修改或错误修复。

CodeQwen 是出色的 SQL 专家

    CodeQwen1.5 可以作为一个智能的 SQL 专家,弥合了非编程专业人士与高效数据交互之间的差距。它通过自然语言使无编程专业知识的用户能够查询数据库,从而缓解了与SQL相关的陡峭学习曲线。

2.2.CodeQwen1.5-7B-Chat

CodeQwen1.5 is the Code-Specific version of Qwen1.5. It is a transformer-based decoder-only language model pretrained on a large amount of data of codes.

  • Strong code generation capabilities and competitve performance across a series of benchmarks;
  • Supporting long context understanding and generation with the context length of 64K tokens;
  • Supporting 92 coding languages
  • Excellent performance in text-to-SQL, bug fix, etc.

三、前置条件

3.1.基础环境

操作系统:centos7

Tesla V100-SXM2-32GB  CUDA Version: 12.2

3.2.下载模型

huggingface:

https://huggingface.co/Qwen/CodeQwen1.5-7B-Chat/tree/main

ModelScope:

git clone https://www.modelscope.cn/qwen/CodeQwen1.5-7B-Chat.git

PS:

1. 根据实际情况选择不同规格的模型

3.3.更新transformers库

pip install --upgrade transformers==4.38.1

四、使用方式

4.1.基础代码

  1. # -*- coding = utf-8 -*-
  2. from transformers import AutoModelForCausalLM, AutoTokenizer, GenerationConfig
  3. device = "cuda"
  4. modelPath='/model/CodeQwen1.5-7B-Chat'
  5. def loadTokenizer():
  6. # print("loadTokenizer: ", modelPath)
  7. tokenizer = AutoTokenizer.from_pretrained(modelPath)
  8. return tokenizer
  9. def loadModel(config):
  10. # print("loadModel: ",modelPath)
  11. model = AutoModelForCausalLM.from_pretrained(
  12. modelPath,
  13. torch_dtype="auto",
  14. device_map="auto"
  15. )
  16. model.generation_config = config
  17. return model
  18. if __name__ == '__main__':
  19. prompt = '需要替换哦'
  20. messages = [
  21. {"role": "system", "content": "You are a helpful assistant."},
  22. {"role": "user", "content": prompt},
  23. ]
  24. config = GenerationConfig.from_pretrained(modelPath, top_p=0.85, temperature=0.1, repetition_penalty=1.1,do_sample=True, max_new_tokens=8192)
  25. tokenizer = loadTokenizer()
  26. model = loadModel(config)
  27. text = tokenizer.apply_chat_template(
  28. messages,
  29. tokenize=False,
  30. add_generation_prompt=True
  31. )
  32. model_inputs = tokenizer([text], return_tensors="pt").to(device)
  33. generated_ids = model.generate(
  34. model_inputs.input_ids
  35. )
  36. generated_ids = [
  37. output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)
  38. ]
  39. response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
  40. print(response)

4.2.安全漏洞检测

把基础代码的prompt替换成以下文本

  1. '''
  2. 请分析下面代码,是否存在安全漏洞,具体代码如下:
  3. import java.sql.Connection;
  4. import java.sql.DriverManager;
  5. import java.sql.ResultSet;
  6. import java.sql.SQLException;
  7. import java.sql.Statement;
  8. public class UserLogin {
  9. public static void main(String[] args) {
  10. String username = "admin";
  11. String password = "password";
  12. try {
  13. // 建立数据库连接
  14. Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydatabase", "root", "password");
  15. // 执行查询
  16. Statement statement = connection.createStatement();
  17. String query = "SELECT * FROM users WHERE username='" + username + "' AND password='" + password + "'";
  18. ResultSet resultSet = statement.executeQuery(query);
  19. // 处理查询结果
  20. if (resultSet.next()) {
  21. System.out.println("登录成功");
  22. } else {
  23. System.out.println("登录失败");
  24. }
  25. // 关闭连接
  26. resultSet.close();
  27. statement.close();
  28. connection.close();
  29. } catch (SQLException e) {
  30. e.printStackTrace();
  31. }
  32. }
  33. }
  34. '''

调用结果:

结论:

模型能分析出代码漏洞并给出优化建议

4.3.优化代码性能

把基础代码的prompt替换成以下文本

  1. '''
  2. 请优化下面代码,提升运行性能,具体代码如下:
  3. public class StringConcatenation {
  4. public static void main(String[] args) {
  5. int n = 10000;
  6. String result = "";
  7. for (int i = 0; i < n; i++) {
  8. result += " " + i;
  9. }
  10. System.out.println(result);
  11. }
  12. }
  13. '''

调用结果:

结论:

模型能分析出循环拼接字符串带来的性能问题,并给出更优的实现方式

4.4.代码翻译

把基础代码的prompt替换成以下文本

  1. '''
  2. 请用Java语言改写下面代码,并实现一致的功能,具体代码如下:
  3. def bubble_sort(arr):
  4. n = len(arr)
  5. # 遍历所有数组元素
  6. for i in range(n):
  7. # Last i elements are already in place
  8. for j in range(0, n-i-1):
  9. # 遍历数组从 0 到 n-i-1
  10. # 交换如果元素发现大于下一个元素
  11. if arr[j] > arr[j+1] :
  12. arr[j], arr[j+1] = arr[j+1], arr[j]
  13. # 示例
  14. arr = [64, 34, 25, 12, 22, 11, 90]
  15. bubble_sort(arr)
  16. print("排序后的数组为:")
  17. for i in range(len(arr)):
  18. print("%d" %arr[i], end=" ")
  19. '''

调用结果:

结论:

模型能理解基于python语言实现的冒泡算法,并转换成Java语言实现类似功能

4.5.生成代码注释

把基础代码的prompt替换成以下文本

  1. '''
  2. 请分析下面代码,给出每行的代码注释,具体代码如下:
  3. def train_step(self, batch: Dict, batch_n_steps: int, step: int, loader_start_time: float) -> Tuple[Dict, Dict]:
  4. self.callbacks.on_train_step_start(self)
  5. # format data
  6. batch = self.format_batch(batch)
  7. loader_time = time.time() - loader_start_time
  8. # conteainers to hold model outputs and losses for each optimizer.
  9. outputs_per_optimizer = None
  10. loss_dict = {}
  11. # OPTIMIZATION
  12. if isimplemented(self.model, "optimize"): # pylint: disable=too-many-nested-blocks
  13. # custom optimize for the model
  14. step_time = time.time()
  15. device, dtype = self._get_autocast_args(self.config.mixed_precision, self.config.precision)
  16. with torch.autocast(device_type=device, dtype=dtype, enabled=self.config.mixed_precision):
  17. outputs, loss_dict_new = self.model.optimize(
  18. batch,
  19. self,
  20. )
  21. step_time = time.time() - step_time
  22. # If None, skip the step
  23. if outputs is None:
  24. return None, None
  25. # TODO: find a way to log grad_norm for custom optimize
  26. loss_dict_new = self.detach_loss_dict(loss_dict_new, True, None, None)
  27. loss_dict.update(loss_dict_new)
  28. else:
  29. # gradient accumulation
  30. # TODO: grad accumulation for each optimizer
  31. step_optimizer = True
  32. if ((step + 1) % self.grad_accum_steps != 0) and (step + 1 != batch_n_steps):
  33. step_optimizer = False
  34. if not isinstance(self.optimizer, list):
  35. # auto training with a single optimizer
  36. outputs, loss_dict_new, step_time = self.optimize(
  37. batch,
  38. self.model,
  39. self.optimizer,
  40. self.scaler,
  41. self.criterion,
  42. self.scheduler,
  43. self.config,
  44. step_optimizer=step_optimizer,
  45. num_optimizers=1,
  46. )
  47. loss_dict.update(loss_dict_new)
  48. else:
  49. # auto training with multiple optimizers (e.g. GAN)
  50. outputs_per_optimizer = [None] * len(self.optimizer)
  51. total_step_time = 0
  52. for idx, optimizer in enumerate(self.optimizer):
  53. criterion = self.criterion
  54. # scaler = self.scaler[idx] if self.use_amp_scaler else None
  55. scaler = self.scaler
  56. scheduler = None
  57. if self.scheduler is not None:
  58. scheduler = self.scheduler[idx]
  59. outputs, loss_dict_new, step_time = self.optimize(
  60. batch,
  61. self.model,
  62. optimizer,
  63. scaler,
  64. criterion,
  65. scheduler,
  66. self.config,
  67. idx,
  68. step_optimizer=step_optimizer,
  69. num_optimizers=len(self.optimizer),
  70. )
  71. # skip the rest if the model returns None
  72. total_step_time += step_time
  73. outputs_per_optimizer[idx] = outputs
  74. # merge loss_dicts from each optimizer
  75. # rename duplicates with the optimizer idx
  76. # if None, model skipped this optimizer
  77. if loss_dict_new is not None:
  78. for k, v in loss_dict_new.items():
  79. if k in loss_dict:
  80. loss_dict[f"{k}-{idx}"] = v
  81. else:
  82. loss_dict[k] = v
  83. step_time = total_step_time
  84. outputs = outputs_per_optimizer
  85. # clear any pesky gradients after gradient accumulation
  86. if step_optimizer:
  87. self.model.zero_grad(set_to_none=True)
  88. # update avg runtime stats
  89. keep_avg_update = {}
  90. keep_avg_update["avg_loader_time"] = loader_time
  91. keep_avg_update["avg_step_time"] = step_time
  92. self.keep_avg_train.update_values(keep_avg_update)
  93. # update avg loss stats
  94. update_eval_values = {}
  95. for key, value in loss_dict.items():
  96. update_eval_values["avg_" + key] = value
  97. self.keep_avg_train.update_values(update_eval_values)
  98. # print training progress
  99. if self.total_steps_done % self.config.print_step == 0:
  100. # log learning rates
  101. lrs = {}
  102. if isinstance(self.optimizer, list):
  103. for idx, optimizer in enumerate(self.optimizer):
  104. current_lr = self.optimizer[idx].param_groups[0]["lr"]
  105. lrs.update({f"current_lr_{idx}": current_lr})
  106. elif isinstance(self.optimizer, dict):
  107. for key, optimizer in self.optimizer.items():
  108. current_lr = self.optimizer[key].param_groups[0]["lr"]
  109. lrs.update({f"current_lr_{key}": current_lr})
  110. else:
  111. current_lr = self.optimizer.param_groups[0]["lr"]
  112. lrs = {"current_lr": current_lr}
  113. # log run-time stats
  114. loss_dict.update(lrs)
  115. loss_dict.update(
  116. {
  117. "step_time": round(step_time, 4),
  118. "loader_time": round(loader_time, 4),
  119. }
  120. )
  121. self.c_logger.print_train_step(
  122. batch_n_steps,
  123. step,
  124. self.total_steps_done,
  125. loss_dict,
  126. self.keep_avg_train.avg_values,
  127. )
  128. if self.args.rank == 0:
  129. # Plot Training Iter Stats
  130. # reduce TB load and don't log every step
  131. if self.total_steps_done % self.config.plot_step == 0:
  132. self.dashboard_logger.train_step_stats(self.total_steps_done, loss_dict)
  133. if self.total_steps_done % self.config.save_step == 0 and self.total_steps_done != 0:
  134. if self.config.save_checkpoints:
  135. # checkpoint the model
  136. self.save_checkpoint()
  137. if self.total_steps_done % self.config.log_model_step == 0:
  138. # log checkpoint as artifact
  139. self.update_training_dashboard_logger(batch=batch, outputs=outputs)
  140. self.dashboard_logger.flush()
  141. self.total_steps_done += 1
  142. self.callbacks.on_train_step_end(self)
  143. return outputs, loss_dict
  144. '''

调用结果:

结论:

模型能理解代码逻辑,并给出关键代码的注释


五、附带说明

5.1.代码专家模型适用的使用场景

  1. 代码自动补全和建议:根据输入的代码片段或上下文,提供下一个可能的代码补全或建议,帮助开发人员提高编码效率。

  2. 代码错误检测和修复:分析代码,并根据语法规则和最佳实践检测潜在的错误或问题,并提供修复建议。

  3. 代码重构和优化:分析现有的代码,并提供重构建议,帮助改进代码结构、提高性能或可读性。

  4. 代码文档生成:根据代码片段或函数、方法等的名称和注释生成相应的文档,提供代码的说明和用法示例。

  5. 代码解释和教学:根据代码片段或问题,解释代码的功能和工作原理,并提供相应的教学示例和资源。

  6. 代码安全分析:帮助检测潜在的安全漏洞和弱点,并提供相应的建议和解决方案,以提高代码的安全性。

  7. 代码翻译和跨语言支持:将一种编程语言的代码翻译成另一种编程语言,帮助开发人员在不同的语言之间进行转换和迁移。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/627100
推荐阅读
相关标签
  

闽ICP备14008679号