★★★ 本文源自AlStudio社区精品项目,【点击此处】查看更多精品内容 >>>

项目简介

一句话项目简介:使用Bing crawler + ChatYuan V2 平替 duckduckgo_search + ChatGLM-6B方案
实现思路很简单,实时搜索 + 可用的大模型(基础模型很重要)

1、https://github.com/deedy5/duckduckgo_search
2、https://github.com/THUDM/ChatGLM-6B
3、https://mp.weixin.qq.com/s/77lY9ITSaC_SwdwyLiN17A

更新:
[2023/04/05] 创建项目,编写基础程序,notebook版测试完成,初次使用Gradio,好多坑和小Bug,待修补…
[2023/04/06] 优化代码,把对应的网页链接展示出来;优化Gradio代码,测试通过…

# 更新paddlenlp的版本
!pip install --upgrade paddlenlp

模型下载

!unzip -d ./model /home/aistudio/data/data202724/chatYuan.zip
# # 使用下方代码在线下载模型,速度视当前平台网速快慢
# from paddlenlp.transformers.t5.tokenizer import T5Tokenizer
# from paddlenlp.transformers.t5.modeling import T5ForConditionalGeneration

# model_name = "ClueAI/ChatYuan-large-v2-paddle"
# tokenizer = T5Tokenizer.from_pretrained(model_name, from_hf_hub=True)
# model = T5ForConditionalGeneration.from_pretrained(model_name, from_hf_hub=True)

# 若通过解压模型到本地的方式,使用下方代码加载
from paddlenlp.transformers.t5.tokenizer import T5Tokenizer
from paddlenlp.transformers.t5.modeling import T5ForConditionalGeneration

tokenizer = T5Tokenizer.from_pretrained("model/chatYuan")
model = T5ForConditionalGeneration.from_pretrained("model/chatYuan")

代码主体

# Part1:大模型生成模块
model.eval()
# 输入前处理
def preprocess(text):
  text = text.replace("\n", "\\n").replace("\t", "\\t")
  return text
# 输出后处理 
def postprocess(text):
  return text.replace("\\n", "\n").replace("\\t", "\t")
# 模型回答
def answer(text, sample=True, top_p=1, temperature=0.7):
    '''sample:是否抽样。生成任务,可以设置为True;
    top_p:0-1之间,生成的内容越多样'''
    text = preprocess(text)
    # 编码输入
    encoding = tokenizer(text=[text], truncation=True, padding=True, max_length=768, return_tensors="pd")
    # 生成
    if not sample:
        out = model.generate(**encoding,
                              return_dict_in_generate=True, 
                              output_scores=False, 
                              max_length=512,
                              max_new_tokens=2048, 
                              num_beams=1, 
                              length_penalty=0.6,
                              no_repeat_ngram_size=12,
                              top_p=top_p, 
                              temperature=temperature
                              )
    else:
        out = model.generate(**encoding, 
                              return_dict_in_generate=True, 
                              output_scores=False,
                              max_length=512, 
                              max_new_tokens=512, 
                              do_sample=True, 
                              top_p=top_p, 
                              temperature=temperature, 
                              no_repeat_ngram_size=3
                              )
    # 解码
    out_text = tokenizer.batch_decode(out[0], skip_special_tokens=True)
    # 返回结果
    return postprocess(out_text[0])
# Part2:网页搜索模块
import requests
from bs4 import BeautifulSoup
import re
import time

headers = {
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
        'Accept-Encoding': 'gzip, deflate, compress',
        'Accept-Language': 'en-us;q=0.5,en;q=0.3',
        'Cache-Control': 'max-age=0',
        'Connection': 'keep-alive',
        'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:22.0) Gecko/20100101 Firefox/22.0'
    }

# 获取搜索结果
def get_search_results(query,max_results=5):
    url = 'http://www.bing.com/search'
    params = {'q': query}
    response = requests.get(url, params=params, headers=headers)
    time.sleep(2)  
    if response.status_code == 200:
        results = []
        soup = BeautifulSoup(response.content, 'html.parser')
        urlAnswers = soup.findAll('li', {'class': 'b_algo'})
        urlAnswers = urlAnswers[:max_results]
        for li in urlAnswers:
            result = {}
            result['link'] = li.find('a',{'class':'sh_favicon'})['href']
            result['title'] = li.find('h2').get_text()
            result['body'] = li.find('p').get_text()
            results.append(result)
        return results
    else:
        print('请求失败')

# 搜索网页
def search_web(query,max_results=3):
    search_results = get_search_results(query, max_results)
    content = set()
    for idx, result in enumerate(search_results):
        adds = result["title"] + '\n' + result["body"]
        adds = adds.replace("...","")
        content.add(adds)
    return '\n'.join(content)   

# Part3:web chat输出模块 + 可加Prompt
# 语言模型推断函数
def Inference_LLM(query):
    input_text = "用户:" + query + "\n小元:"
    predict = answer(input_text, sample=True,top_p=1, temperature=0.7)
    return predict
# web chat输出
def chat_web(query):
    prompt = query
    if '[WEB]' in query:
        query = query.replace('[WEB]','')
        content = search_web(query)
        prompt = "给定以下内容:{web_content}。请回答:{query}。".format(web_content=content, query=query)
    print("query:", query)
    answer = Inference_LLM(prompt)
    print("answer:", answer)
    print('******'*10)
# “[WEB]” 会进行联网搜索
if __name__ == '__main__':
    while True:
        query = input("enter an query to search:").strip()
        if query == "quit":
            break
        chat_web(query)
enter an query to search: [WEB]如何制作一碗牛肉面?


query: 如何制作一碗牛肉面?
answer: 制作一碗牛肉面需要准备以下材料:
- 牛肉片
- 1 杯水
- 2 片葱
- 3 片姜
- 4 片蒜
- 5 片干辣椒
- 6 片花椒
- 7 片八角
- 10 粒香叶
- 一个八角茴香
- a 杯生抽
- b 杯老抽
- c 杯料酒
- d 杯盐
- f 杯胡椒粉
- g 杯鸡精
- h 杯香油
- I 杯香菜
- J 杯葱花
- K 杯蒜泥
- L 杯芝麻油
- N 杯食用油
- O 杯清水
- P 杯面粉
- R 杯温水
- S 杯油

步骤:
1. 购买市场上卖的酱牛肉,回家切成薄片。
2. 锅上做水烧开,放入牛肉片,煮至开水变白后放入自己压好的面条(比较劲道),煮熟出锅前,放入几片嫩嫩的油...
************************************************************


enter an query to search: 如何制作一碗牛肉面?


query: 如何制作一碗牛肉面?
answer: 牛肉面的做法:

材料:
- 牛肉
- 黄豆芽
- 马齿苋
- 金针菜
- 陈醋
-葱
-姜
-蒜
-料酒
-生抽
-老抽
-盐
-鸡精
-胡椒粉

步骤:
1. 将牛肉切成薄片,用盐和料酒腌制10分钟。
2. 将黄豆芽洗净,切成小段。
3. 将马齿苋洗净,切碎。
4. 将金针菜洗净,撕成小朵。
5. 将葱、姜、蒜洗净,切末。
6. 将料酒、生抽、老抽、盐、鸡精、胡椒粉混合在一起,搅拌均匀。
7. 将腌制好的牛肉片放入碗中,加入混合好的调料,搅拌均匀,腌制10分钟左右。
8. 将面条放入碗中。
9. 将煮好的面条捞出,沥干水分。
10. 将煮熟的牛肉片放在面条上,淋上煮好的牛肉汤。
11. 将切好的黄豆芽、马齿菜、金针蔬菜、陈醋、生抽和老抽均匀地撒在面条上。
12. 将葱花、姜蒜末、蒜泥、香油和胡椒粉均匀地洒在面条的表面。
13. 将面盛入碗中,撒上葱花和香菜即可。

提示:
牛肉的肉质细嫩,口感鲜美,但不宜过多食用。
************************************************************


enter an query to search: [WEB]特朗普如果认罪将面临多少年的刑期?


query: 特朗普如果认罪将面临多少年的刑期?
answer: 如果特朗普认罪,他可能面临136年的监禁。但是,如果他被判有罪,实际刑期可能会远低于这个数字。
************************************************************


enter an query to search: quit

优化和封装

# 封装为一个Class方便调用,完整代码如下
import requests
from bs4 import BeautifulSoup
import time
from paddlenlp.transformers.t5.tokenizer import T5Tokenizer
from paddlenlp.transformers.t5.modeling import T5ForConditionalGeneration

headers = {
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
        'Accept-Encoding': 'gzip, deflate, compress',
        'Accept-Language': 'en-us;q=0.5,en;q=0.3',
        'Cache-Control': 'max-age=0',
        'Connection': 'keep-alive',
        'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:22.0) Gecko/20100101 Firefox/22.0'
}

class ChatYuan_LLM:
    def __init__(self, model_path="ClueAI/ChatYuan-large-v2-paddle"):
        self.tokenizer = T5Tokenizer.from_pretrained(model_path)
        self.model = T5ForConditionalGeneration.from_pretrained(model_path)
        self.model.eval()

    # 数据处理
    def preprocess(self, text):
        text = text.replace("\n", "\\n").replace("\t", "\\t")
        return text
    def postprocess(self, text):
        return text.replace("\\n", "\n").replace("\\t", "\t")

    def answer(self, text, sample=True, top_p=1, temperature=0.7):
        '''sample:是否抽样。生成任务,可以设置为True;
        top_p:0-1之间,生成的内容越多样'''
        text = self.preprocess(text)
        encoding = self.tokenizer(text=[text], truncation=True, padding=True, max_length=768, return_tensors="pd")
        if not sample:
            out = self.model.generate(**encoding, return_dict_in_generate=True, output_scores=False, max_length=512,
            max_new_tokens=2048, num_beams=1, length_penalty=0.6,
            no_repeat_ngram_size=12,
            top_p=top_p, temperature=temperature)
        else:
            out = self.model.generate(**encoding, return_dict_in_generate=True, output_scores=False, max_length=512, max_new_tokens=512, do_sample=True, top_p=top_p, temperature=temperature, no_repeat_ngram_size=3)

            out_text = self.tokenizer.batch_decode(out[0], skip_special_tokens=True)
        return self.postprocess(out_text[0])

    def get_search_results(self,query,max_results=5):
        url = 'http://www.bing.com/search'
        params = {'q': query}
        response = requests.get(url, params=params, headers=headers)
        time.sleep(1)  
        if response.status_code == 200:
            results = []
            soup = BeautifulSoup(response.content, 'html.parser')
            urlAnswers = soup.findAll('li', {'class': 'b_algo'})
            urlAnswers = urlAnswers[:max_results]
            for li in urlAnswers:
                result = {}
                result['link'] = li.find('a',{'class':'sh_favicon'})['href']
                result['title'] = li.find('h2').get_text()
                result['body'] = li.find('p').get_text()
                results.append(result)
            return results
        else:
            print('请求失败')
            return ''

    def search_web(self,query,max_results=3):
        search_results = self.get_search_results(query, max_results)
        content = set()
        for idx, result in enumerate(search_results):
            adds = result["title"] + '\n' + result["body"]
            adds = adds.replace("...","")
            content.add(adds)
        return '\n'.join(content),[f"{i['title']}:{i['link']}" for i in search_results]  

    def Inference_LLM(self, query, top_p, temperature):
        input_text = "用户:" + query + "\n小元:"
        predict = self.answer(input_text, sample=True, top_p=top_p, temperature=temperature)
        return predict

    def chat_web(self, query, top_p=1.0, temperature=0.7):
        if '[WEB]' in query:
            query = query.replace('[WEB]','')
            content,reference = self.search_web(query)
            prompt = "给定以下内容:{web_content}。请回答:{query}。".format(web_content=content, query=query)
            answer = self.Inference_LLM(prompt, top_p, temperature)
            answer_with_refs = answer
            if reference:
                refs = [f"[{i+1}] '{r}'" for i, r in enumerate(reference)]
                answer_with_refs += "\n" + "\n".join(refs)
            return answer_with_refs
        else:
            answer = self.Inference_LLM(query, top_p, temperature)
            return answer
# from LLM import ChatYuan_LLM
chatAPI = ChatYuan_LLM()
message = "[WEB]查询马克龙访华的日期"
chatAPI.chat_web(message)
('马克龙访华的日期为2023年4月5日至7日。',
 ['[新闻直播间]马克龙与冯德莱恩今起访华 推动中法 中欧经贸合作:https://tv.cctv.com/2023/04/05/VIDEZHcL6YvMyUnvGBQTlles230405.shtml',
  '马克龙已抵达!此次和冯德莱恩一同访华 三大看点引关注 ...:https://fund.eastmoney.com/a/202304052683493130.html',
  '马克龙和冯德莱恩5日访华 法媒:寻找外交平衡_新闻中心 ...:http://news.china.com.cn/2023-04/04/content_85209895.htm'])

结果

message = "[WEB]查询马克龙访华的日期"
chatAPI.chat_web(message)
"马克龙访华的日期为2023年4月5日至7日。\n[1] '马克龙、冯德莱恩明天抵京!欧洲政要纷至,释放三个信号 ...:https://news.sina.com.cn/c/2023-04-04/doc-imypevxk9826357.shtml'\n[2] '马克龙、冯德莱恩5日至7日访华,空客在内的60名高管随行:https://finance.sina.com.cn/jjxw/2023-04-04/doc-imypeezr3108324.shtml'\n[3] '法国总统马克龙称将于4月初访华,此前多次表达来访意愿:https://www.guancha.cn/internation/2023_02_25_681483.shtml'"

此文章为搬运
原项目链接

Logo

学大模型,用大模型上飞桨星河社区!每天8点V100G算力免费领!免费领取ERNIE 4.0 100w Token >>>

更多推荐