前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【第十届 Sky Hackathon】本地开发环境搭建

【第十届 Sky Hackathon】本地开发环境搭建

原创
作者头像
IT蜗壳-Tango
发布2024-07-14 01:23:48
25800
代码可运行
发布2024-07-14 01:23:48
举报
文章被收录于专栏:机器学习
运行总次数:0
代码可运行

前言

随着大型语言模型(LLMs)的发展与广泛应用,我们正身处一个技术革新的时代。尤其是以检索为基础的系统,在这场技术飞跃中走在了最前沿。这些模型不仅仅是自动化的工具,它们更是提高生产力的得力助手,能够与各种工具和文档进行交互,展开有根据的对话。

为了深入挖掘和探索这一技术的潜力,我们诚挚地邀请您参加NVIDIA 第十届Sky Hackathon活动。本次活动将聚焦于大型语言模型的实际部署以及为满足用户和深度学习模型需求所需的高效实施策略。

本次Sky Hackathon的核心议题是“基于RAG技术创新构建智能对话机器人 ”。我们鼓励参赛者运用RAG(Retrieval-Augmented Generation)技术,并结合NVIDIA的SDK工具,自主设计和搭建对话机器人。通过这一过程,您将亲身体验从数据检索到生成对话的完整流程,并深入了解NVIDIA SDK在生成式AI领域的实际应用。

引自官方比赛说明

为了更好的开发本次活动的项目,我们先在本地电脑上搭建一个开发环境,进行本地项目开发。

如果有Ubuntu系统是最好的,如果没有的话,可以使用WSL2来代替

创建虚拟环境

官方环境使用的应该是Python3.8,所以我们也使用这个版本

现在Ubuntu环境中安装好miniconda

代码语言:bash
复制
mkdir -p ~/miniconda3
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O ~/miniconda3/miniconda.sh
bash ~/miniconda3/miniconda.sh -b -u -p ~/miniconda3
rm -rf ~/miniconda3/miniconda.sh

~/miniconda3/bin/conda init bash
~/miniconda3/bin/conda init zsh
代码语言:bash
复制
 conda create -n nv python=3.8 -y

为了后续我们方便调试,我们使用jupyterlab来做为开发环境

代码语言:bash
复制
conda activate nv
pip install jupyter
pip install ipykernel -i https://pypi.tuna.tsinghua.edu.cn/simple
python -m ipykernel install --name=nv_py38

进入到我们的工作目录并启动notebook

代码语言:bash
复制
 mkdir -p work/nv
 cd work/nv/
 jupyter-lib

我们点击上面的链接会在电脑上打开一个网站

打开一个终端,安装我们本次活动需要的依赖库

代码语言:bash
复制
gradio
faiss-cpu==1.7.4
llama-index==0.9.22
langchain==0.0.352
langchain-nvidia-ai-endpoints==0.0.11

创建API key

我们访问Try NVIDIA NIM APIs

Baseline中使用的是ai-nemotron-4-340b-instruct,因此我们点击这个banner,然后创建个API KEY

点击生成Key

将生成的key保存下来,但是注意他是会过期的

测试模型

我们需要将上面的模型加载下来,并测试一下效果

代码语言:python
代码运行次数:0
复制
llm = ChatNVIDIA(model="ai-nemotron-4-340b-instruct")
result = llm.invoke("what is nemo")
print(result.content)

运行后,可以看到输出效果。

设置Embedding模型

代码语言:python
代码运行次数:0
复制
embedder = NVIDIAEmbeddings(model="ai-embed-qa-4")
embedder.embed_query("test")

加载数据

我们可以使用这次比赛准备的测数据,当然也可以使用自己的数据

也可以使用自己的数据

例如我这里添加了一个关于软考高级架构师考试的介绍的内容。

代码语言:python
代码运行次数:0
复制
from tqdm import tqdm
from pathlib import Path

# 在这里我们读入文本数据并将它们准备到 vectorstore 中
ps = os.listdir("./zh_data/")
data = []
sources = []
docs_name = []
for p in ps:
    if p.endswith('.txt'):
        path2file="./zh_data/"+p
        docs_name.append(path2file)
        with open(path2file,encoding="utf-8") as f:
            lines=f.readlines()
            for line in lines:
                if len(line)>=1:
                    data.append(line)
                    sources.append(path2file)

documents=[d for d in data if d != '\n']
len(data), len(documents), data[0]

创建vectorstore

代码语言:python
代码运行次数:0
复制
from langchain.text_splitter import CharacterTextSplitter
text_splitter = CharacterTextSplitter(chunk_size=400, separator=" ")
docs = []
metadatas = []

生成embed数据

代码语言:python
代码运行次数:0
复制
for i, d in enumerate(documents):
    splits = text_splitter.split_text(d)
    #print(len(splits))
    docs.extend(splits)
    metadatas.extend([{"source": sources[i]}] * len(splits))
### 将创建好的embed存储到本地
store = FAISS.from_texts(docs, embedder , metadatas=metadatas)
store.save_local('./embed')

这一步需要花费一点时间,如果数据没有发生变化的情况下,可以不用重新执行。

读取本地生成好的的数据

代码语言:python
代码运行次数:0
复制
vecstores = [FAISS.load_local(folder_path="./embed/", embeddings=embedder)]

设置default_FAISS() 函数,初始化空向量存储,通过convstore储存对话向量

设置aggregate_vstores()函数将有用的文档信息存储在 docstore变量中

代码语言:python
代码运行次数:0
复制
embed_dims = len(embedder.embed_query("test"))
def default_FAISS():
    '''Useful utility for making an empty FAISS vectorstore'''
    return FAISS(
        embedding_function=embedder,
        index=IndexFlatL2(embed_dims),
        docstore=InMemoryDocstore(),
        index_to_docstore_id={},
        normalize_L2=False
    )

def aggregate_vstores(vectorstores):
    ## 初始化一个空的 FAISS 索引并将其他索引合并到其中
    agg_vstore = default_FAISS()
    for vstore in vectorstores:
        agg_vstore.merge_from(vstore)
    return agg_vstore

if 'docstore' not in globals():
    docstore = aggregate_vstores(vecstores)

print(f"Constructed aggregate docstore with {len(docstore.docstore._dict)} chunks")
llm = ChatNVIDIA(model="ai-nemotron-4-340b-instruct") | StrOutputParser()
convstore = default_FAISS()

构建RAG 链

  • 自动对话存储:save_memory_and_get_output函数允许向我们的对话添加新条目
  • doc2str:将文本分块转换成上下文字符串格式输出。
  • prompt提示和结构。
  • 构建retrieval_chain
  • 设置对话生成函数chat_gen()
代码语言:python
代码运行次数:0
复制
doc_names_string = "\n"
for doc_name in docs_name:
    doc_names_string += doc_name+"\n"
    
def save_memory_and_get_output(d, vstore):
    """Accepts 'input'/'output' dictionary and saves to convstore"""
    vstore.add_texts([
        f"User previously responded with {d.get('input')}",
        f"Agent previously responded with {d.get('output')}"
    ])
    return d.get('output')

initial_msg = (
    "Hello! I am a document chat agent here to help the user!"
    f" I have access to the following documents: {doc_names_string}\n\nHow can I help you?"
)

chat_prompt = ChatPromptTemplate.from_messages([("system",
    "You are a document chatbot. Help the user as they ask questions about documents."
    " User messaged just asked: {input}\n\n"
    " From this, we have retrieved the following potentially-useful info: "
    " Conversation History Retrieval:\n{history}\n\n"
    " Document Retrieval:\n{context}\n\n"
    " (Answer only from retrieval. Only cite sources that are used. Make your response conversational.Reply must more than 100 words)"
), ('user', '{input}')])

## Utility Runnables/Methods
def RPrint(preface=""):
    """Simple passthrough "prints, then returns" chain"""
    def print_and_return(x, preface):
        print(f"{preface}{x}")
        return x
    return RunnableLambda(partial(print_and_return, preface=preface))

def docs2str(docs, title="Document"):
    """Useful utility for making chunks into context string. Optional, but useful"""
    out_str = ""
    for doc in docs:
        doc_name = getattr(doc, 'metadata', {}).get('Title', title)
        if doc_name:
            out_str += f"[Quote from {doc_name}] "
        out_str += getattr(doc, 'page_content', str(doc)) + "\n"
    return out_str

## 将较长的文档重新排序到输出文本的中心, RunnableLambda在链中运行无参自定义函数 ,长上下文重排序(LongContextReorder)
long_reorder = RunnableLambda(LongContextReorder().transform_documents)

retrieval_chain = (
    {'input' : (lambda x: x)}
    | RunnableAssign({'history' : itemgetter('input') | convstore.as_retriever() | long_reorder | docs2str})
    | RunnableAssign({'context' : itemgetter('input') | docstore.as_retriever()  | long_reorder | docs2str})
    | RPrint()
)
stream_chain = chat_prompt | llm

def chat_gen(message, history=[], return_buffer=True):
    buffer = ""
    ##首先根据输入的消息进行检索
    retrieval = retrieval_chain.invoke(message)
    line_buffer = ""

    ## 然后流式传输stream_chain的结果
    for token in stream_chain.stream(retrieval):
        buffer += token
        ## 优化信息打印的格式
        if not return_buffer:
            line_buffer += token
            if "\n" in line_buffer:
                line_buffer = ""
            if ((len(line_buffer)>84 and token and token[0] == " ") or len(line_buffer)>100):
                line_buffer = ""
                yield "\n"
                token = "  " + token.lstrip()
        yield buffer if return_buffer else token

    ##最后将聊天内容保存到对话内存缓冲区中
    save_memory_and_get_output({'input':  message, 'output': buffer}, convstore)

使用Gradio框架构建前端RAG机器人界面与您的 Gradio 聊天机器人互动

代码语言:python
代码运行次数:0
复制
chatbot = gr.Chatbot(value = [[None, initial_msg]])
demo = gr.ChatInterface(chat_gen, chatbot=chatbot).queue()

try:
    demo.launch(debug=True, share=False, show_api=False, server_port=5000, server_name="0.0.0.0")
    demo.close()
except Exception as e:
    demo.close()
    print(e)
    raise e

运行后,我们在notebook中会看到一个界面,如果你觉得在这里操作不方便的话,也可以在浏览器中打开

至此,我们的基础环境已经准备好了,剩下就是好好的发挥自己的创建。来完成本次比赛了。

最后

为什么要在本地拆创建环境呢?

主要要是本地次比赛为了不让大家太卷,服务器每天10点就关闭了,第二天9点才开启,我们上班的小伙伴表示时间根本不够用啊,因此在本地创建一个开发环境是非常必要的。

好了,环境搭建部分即使这些了,更多的内容,等我比赛完成后再和大家继续分享了。我是Tango,一个热爱分享各种技术的程序猿,我们下期见。


我正在参与2024腾讯技术创作特训营最新征文,快来和我瓜分大奖!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 创建虚拟环境
  • 创建API key
  • 测试模型
  • 设置Embedding模型
  • 加载数据
  • 创建vectorstore
  • 构建RAG 链
  • 使用Gradio框架构建前端RAG机器人界面与您的 Gradio 聊天机器人互动
  • 最后
相关产品与服务
对话机器人
对话机器人(Conversation Robot,ICR),是基于人工智能技术,面向企业场景的 AI 服务,可应用于智能客服、服务咨询、业务办理等场景。本产品旨在帮助企业快速构建,满足自身业务诉求的对话机器人,从而减少企业人力成本或解决服务不及时问题。用户可通过对话机器人用户端引擎,实现高准确率的对话服务。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档