让AI给你写代码(六)- 结合语意匹配,引导AI小助手逐步完善代码,新增功能(上)

文章介绍了如何利用AI技术,通过格式化对话和语义匹配,实现对单个文件的代码修改、保存以及执行的功能,并计划构建一个完整的AI辅助编码应用。通过改进流程,用户可以直接提出操作请求,如打开文件、执行代码等,AI助手能理解和响应这些指令。
摘要由CSDN通过智能技术生成

本文是接着让AI给你写代码,初体验(三)- AI加上格式化对话,实现对单个文件的修改/保存

回顾一下当时实现的需求,对AI生成代码实现保存,然后再打开,修订后再保存。 那么能不能再往前进一步,真正实现输入文字需求,逐步引导AI小助手生成代码、然后执行代码,保存代码,并且在原代码基础上,根据新增输入提示需求,修改或者新增代码实现功能的逐步集成,进而构建一个较为完整的AI辅助编码的应用(仍然使用通义千问大模型)。
我们分为上下两部分分享,上半部分将应用代码的修改,下半部分,用一个例子实现用提示最后生成代码,包含应用数据获取及绘图,这里先说上半部分。

先回顾一下AI加格式化对话实现对单个文件的修改和保存的流程:
主人: 要求打开本地指定代码
小助手: 打开本地指定代码,并反显
主人:要求结合这段代码和新需求,增加一个功能
小助手: 将这段代码和新需求提交给AI,并反显AI给出的建议
主人: 要求修改
小助手:将修改要求提交给AI,并反显AI给出的建议
主人:要求合并代码
小助手:将合并代码的要求提交AI,并反显
主人: 要求保存代码
小助手:将AI给的代码提取保持
主人:退出对话
小助手:结束对话

现在这个流程基本上可以改进为(斜体部分)
主人: 要求打开本地指定代码
小助手: 打开本地指定代码,并反显
主人:要求结合这段代码和新需求,增加/修改一个功能
小助手: 将这段代码和新需求提交给AI,并给出新增功能后的代码
主人要求执行代码
小助手执行代码并反显结果
主人要求保存代码
小助手将AI给的代码保存到指定文件

主人:要求退出对话
小助手:结束对话
(执行功能目前仅限于python)
然后用相近语意识别改进格式化正则匹配,使得小助手更加智能一些,例如输入“请打开文件XXXX”,““麻烦打开XXX文件” AI小助手都可以识别到**“打开文件”操作, 输入"请保存代码",“请保存文件”,都可识别为“保存文件”**操作… 此为其一,据此小助手要做的操作可按字典定义为

operation_set = {
    "打开文件": assistant.openFile,
    "保存文件": assistant.saveFile,
    "执行代码": assistant.executeCode,
    "结束对话": assistant.endTalk
}

直接匹配到要操作的函数

这里的关键是选择相似语意匹配的工具,需要注意的必须同时满足两个要求:
1) 这几个操作关键词之间要有足够的区分度
2 ) 与这几个操作关键词不想干的语句需要有足够的区分度
需要用到中文词汇预训练模型或者其他工具,我尝试了及种

  1. HuggingFace的bert-base-chinese预训模型
  2. nltk近义词函数nltk.edit_distance
  3. sentence-transformers的paraphrase-multilingual-MiniLM-L12-v2预训模型

其中,HuggingFace的bert-base-chinese预训模型下载和安装可以参考在Hugging Face上下载并使用Bert-base-Chinese
bert-base-chinese模型可以下载到本地,计算语义相似度的用法如下:

from transformers import BertModel, BertTokenizer
import numpy as np
import torch
class NPLUtil:
    def __init__(self):
        bert_path = "/home/cfets/AI/model/"
        vocab_file = bert_path + "vocab.txt"
        self.tokenizer = BertTokenizer(vocab_file)
        model_path = bert_path + "bert-base-chinese/"
        self.model = BertModel.from_pretrained(model_path)

    def text_similarity(self, text1: str, text2: str):
        # 对输入文本进行tokenize和编码
        inputs = self.tokenizer([text1, text2], return_tensors='pt', padding=True, truncation=True, max_length=32)
        # 将输入传递给BERT模型,并获取输出
        with torch.no_grad():
            outputs = self.model(**inputs)
            embeddings = outputs.last_hidden_state[:, 0, :].cpu().numpy()
            # embeddings = outputs.last_hidden_state

        print(embeddings)
        embedding1 = embeddings[0]
        embedding2 = embeddings[1]

        t_similarity = np.dot(embedding1, embedding2) / (np.linalg.norm(embedding1) * np.linalg.norm(embedding2))
        return t_similarity

if __name__ == '__main__':
    textCompare = NPLUtil()

    sentence1 = "保存文件"
    sentence2 = "打开文件"
    similarity = textCompare.text_similarity(sentence1, sentence2)
    print(f"相似度:{similarity:.4f}")

HuggingFace的bert-base-chinese的问题主要是,操作关键词之间的区分度不够,比如"保存文件"和““打开文件”相似度就是 0.9359,过于相近

nltk近义词函数nltk.edit_distance函数用法:

import nltk
# 加载中文词汇
chinese_vocab = ["打开文件", "保存文件", "保存代码", "执行代码", "结束对话"]
# 输入语意
# input_semantics = "麻烦保存代码"
input_semantics = "保存文件"
# 计算相似度
similarity_scores = {}
for word in chinese_vocab:
    similarity_scores[word] = nltk.edit_distance(input_semantics, word)
    print(similarity_scores[word])
# 找到最相似的词汇
most_similar_word = min(similarity_scores, key=similarity_scores.get)
print("与输入语意最相似的词汇是:", most_similar_word)

计算结果
2
0
2
4
4
与输入语意最相似的词汇是: 保存文件
基本满足要求

sentence-transformers的 paraphrase-multilingual-MiniLM-L12-v2模型,下载安装和初步应用可参考 [原创]python计算中文文本相似度神器

具体应用如下

mport torch
from sentence_transformers.util import cos_sim
from sentence_transformers import SentenceTransformer as SBert

sbert_path = "/home/cfets/AI/model/paraphrase-multilingual-MiniLM-L12-v2"
model = SBert(sbert_path)
sentences1 = ['打开文件',
              '保存文件',
              '执行代码',
              '结束对话'
              ]

sentences2 = ['打开文件',
              '保存文件',
              '执行代码',
              '结束对话'
              ]

# Compute embedding for both lists
embeddings1 = model.encode(sentences1)
embeddings2 = model.encode(sentences2)

# Compute cosine-similarits
cosine_scores = cos_sim(embeddings2, embeddings1)
print(cosine_scores)

res = torch.max(cosine_scores, dim=1, keepdim=False)

print(res.values.numpy().tolist()[0])
print(res.indices.numpy().tolist()[0])
index=res.indices.numpy().tolist()[0]
print(sentences1[index])

计算各操作项的自相似结果矩阵如下:
tensor([[1.0000, 0.5882, 0.4500, 0.3998],
[0.5882, 1.0000, 0.3156, 0.2404],
[0.4500, 0.3156, 1.0000, 0.3043],
[0.3998, 0.2404, 0.3043, 1.0000]])
拉的是比较开的,相对效果比较好 ,当然也不是没有问题,比如"麻烦保存代码",会识别成"执行代码" (nltk.edit_distance函数也会是这个结果),解决办法在操作集中增加1个操作项,“保存代码”和“保存文件”指向的操作一致

operation_set = {
“打开文件”: assistant.openFile,
“保存文件”: assistant.saveFile,
“保存代码”: assistant.saveFile,
“执行代码”: assistant.executeCode,
“结束对话”: assistant.endTalk
}
解决了语意相似性的问题,我们看看主要的代码修改,这里只标注修改部分,原先代码还是请移步让AI给你写代码,初体验(三)
主程序:

# AI对话
def conversation_mutual():
    # 初始化小助手
    assistant = Assistant()
    # 新增: 操作匹配字典
    operation_set = {
        "打开文件": assistant.openFile,
        "保存文件": assistant.saveFile,
        "保存代码": assistant.saveFile,
        "执行代码": assistant.executeCode,
        "结束对话": assistant.endTalk
    }

    # 初始化工具
    textUtil = NPLUtil()
    while True:

        message = input('master:')
        op_reply = ""

        assistant.setMessage(message)   # 向小助手提交主人的消息

        # 修改为匹配操作
        ops = list(operation_set.keys())  # 获得操作列表
        cn_msg = remove_non_chinese(message)   #对输入信息进行预处理,仅保留中文主干
        similarity, operation = textUtil.text_similarity(ops, cn_msg)   #与操作匹配字典进行匹配,返回相似度和匹配到的操作

        if similarity > 0.7:   # 相似度控制 1相等  0不想干
            # 执行操作
            op_reply = operation_set[operation]()   #匹配执行
            print('小助手:', end='')
            print(op_reply, end='')
            if operation == "结束对话":
                break
        else:
            assistant.conversation_ask()  # 提交给AI

        print('\n')

需要注意的是,
1 因为语意匹配对两个待比较的短语长度非常敏感,需要预处理,我们这里简化,去掉英文符号(主要是文件名,路径等),保留中文主干,函数remove_non_chinese如下

def remove_non_chinese(text):
    pattern = re.compile(r'[^\u4e00-\u9fa5]')  # 匹配非中文字符的正则表达式
    chinese_text = re.sub(pattern, '', text)  # 使用正则表达式替换非中文字符为空字符串
    return chinese_text

2 匹配函数就是找一个最接近的操作,为预防误操作因此要控制匹配相似度(similarity),这里选0.7 大致上可以匹配 {‘运行代码’ : ‘执行代码’ } {‘麻烦执行上述代码’ : ‘执行代码’}等等… 如果全部操作匹配不上,就向外网 AI大模型提交

3 匹配函数的归一化处理 op_reply = operation_setoperation #匹配执行 取消参数,参数输入在之前有方法执行 assistant.setMessage(message) # 向小助手提交主人的消息

然后我们看一下 AI助手程序

class Assistant:
    def __init__(self):
        self.message = ""       # 新增本轮主人输入对话
        self.last_content = ""     #  上一次主人输入的内容,比如打开的文件等等
        self.last_AI_message = ""   #    上一次AI反馈的内容
        self.python_path ...

    def setMessage(self, message):   #新增向小助手提交主人的消息的方法
        self.message = message
    ...

    # 打开文件
    def openFile(self):
        content = ""
        try:
            # 按正则表达式,获得全路径文件
            programmingName = filepathMatch(self.message)  #从主人读入的信息获得文件名
           ...

    # 保存文件
    def saveFile(self):
        replyMessages = self.last_AI_message  # 保存AI生成的代码
        ...
        return res  # 增加反馈

    # 保存文件原子操作
    def saveCode(self, programmingName, content_list):
       ...

    # 提交AI对话
    def conversation_ask(self):
       ... 

    def executeCode(self):   # 新增 执行代码(来自于AI生成的代码)
        _, after = self.last_AI_message.split("```python")
        realcode = after.split("```")[0]
        try:
            exec(realcode)
            return "执行成功"
        except Exception as e:
            return "执行失败: %s" % e

    def endTalk(message: str):   # 包装了结束对话
        return "好的,再见"

这里需要说明的是 filepathMatch函数用了正则表达式匹配文件去掉路径后的文件名
为满足匹配需要,至少需要输入 /file.xxx 而不是 file.xxx

全部代码修改如下,下一篇会给一个完整的案例说明如何用提示输入完成代码生成,修改,增加,执行等等…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhyuli

您的鼓励是对我付出努力一种赞赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值