ollama的api部署学习笔记

文档介绍

本文聚焦于使用langchain库实现本地ollama服务器端的部署。尝试根据: 官方教程从基础的操作开始逐渐整合所有的api模块,实现在Python的多模态输入与多模态输出(TTS,T2T,I2T etc.)。最终整合成自己的项目。

后面,本文将会从官方文档的基础api开始整理,一步一步将基础函数与外部接口对接实现进阶功能。并在最后给出完整的项目成果展示。

基础功能

需要重点说明的是,一定要保证服务器/PC/微服务的ollama后台打开了

ollama serve

LLM的定义,输入,提示词与输出

LLM-ollama的 接口生成。通过这个代码可以建立一个ollama指定模型的接口,但模型并未预热,因此在第一次执行的时候依旧可能很慢。

from langchain_community.llms import Ollama
llm = Ollama(model="qwen2.5:14b")

LLM-ollama的 输入。简单的,我们可以通过一行命令就实现写死的文本交流。

llm.invoke("how can langsmith help with testing?")
# LangSmith is a powerful platform developed by Anthropic
# (not Alibaba Cloud) to evaluate and test language models like Claude.

LLM-ollama的 提示词。使用模板的提示词可以帮助模型生成更符合用户要求的输出(by 转化用户的输入为llm更好理解的文本)。

from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
prompt = ChatPromptTemplate.from_messages([
    ("system", "You are a world class technical documentation writer."),
    ("user", "{input}")
])
output_parser = StrOutputParser() #没有它的话,回复就是一个message,但是我们更希望得到的是str
chain = prompt | llm | output_parser 
#注意,此处的invoke接入的信息为一个字典
chain.invoke({"input": "how can langsmith help with testing?"})

LLM-ollama的 输入-输出。以下为一个写好的基础模板,可以参考下面的设置来自定义。

from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_community.llms import Ollama

llm = Ollama(model="qwen2.5:14b") # 自定义模型
prompt = ChatPromptTemplate.from_messages([
    ("system", "You are a world class technical documentation writer."),
    ("user", "{input}")
]) # 自定义提示词与输入字典格式
output_parser = StrOutputParser() #没有它的话,re2回复就是一个message,但是我们更希望得到的是str
chain = prompt | llm | output_parser # 生成所需的api而不只是chatbot

#以下为两种输入形式,分别对应prompt与常规str
text = "What would be a good company name for a company that makes colorful socks?"
messages = {"input": text}

re1 = llm.invoke(text)
# >> Choosing the right company name can make a significant impact on how your brand is perceived. 

re2 = chain.invoke(messages)
#Choosing a company name for a business that specializes in colorful socks should reflect creativity, style, and fun—qualities inherent to the product.

定制自己的提示词

正常的LLM往往不会得到用户的原始输入,所有的文本将被嵌入到指定的提示词模板(Prompt Template)以帮助模型更好的理解用户的需求。

在上文,我们已经介绍了提示词的简单使用,使用一个固定的模板。后面我们将一步一步定制自己的模板。

基础的提示词

from langchain_core.prompts import PromptTemplate

prompt = PromptTemplate.from_template("What is a good name for a company that makes {product}?")
prompt.format(product="colorful socks")
#生成的句子就是:What is a good name for a company that makes colorful socks.

另外,我们还可以通过提示词来帮助模型理解多个用户的信息以及每个信息的前后关系等等,以下是一个示例。

from langchain_core.prompts.chat import ChatPromptTemplate

#这是一个简单的模板,其中预留了需要的语言。
template = "You are a helpful assistant that translates {input_language} to {output_language}." 
#这是一个简单的模板,其中预留了后续用户输入的信息
human_template = "{text}"

#ChatPromptTemplate.from_messages是一个常用的提示词模板,其可以生成多个用户的信息模板整合
#具体来说,system是默认的用户,以帮助模型理解用户的需求(翻译)
#human是定义的用户,也可以写做user等。
#在这个例子中,每个human_template的输入都会被从input_language翻译为output_language。
chat_prompt = ChatPromptTemplate.from_messages([
    ("system", template),
    ("human", human_template),
])

#xxx.format_messages是常用的方法,为预留的提示词空位填充需要的文本
chat_prompt.format_messages(input_language="English", output_language="French", text="I love programming.")

流式

由于langchain对于ollama的说明较少,但是我们还是可以尝试一下。

同步流式输出

使用、同步,一定要保证输出的流程处于函数主循环之中,否则依旧会卡住。

llm = Ollama(
        model="qwen2.5:14b", callback_manager=CallbackManager([StreamingStdOutCallbackHandler()]),
        streaming=True,
    )#注意,此处打开流式输出模式
chains = chat_prompt | llm | output_parser #此处依旧加入了输出转Str方便我们后面出处理
chunks = [] #建立同步输出储存器
for chunk in llm.stream(prompt): #使用stream方法实现同步传输,每次循环会迭代一个输出结果
    chunks.append(chunk) #保存
    print(chunk, end="|", flush=True) # 输出展示
    #TT|TSTS|模型模型|分分|几种几种|,,|像像|基于基于|规则规则|的的|,,|统计统计|参数参数|的的|,,|还有还有|最近最近|流行的流行的|神经神经|网络网络|型型|的的|。。|每每|种种|都有都有|特点特点|,,|用用|处处|也也|不同不同|。。||
    #['T', 'TS', '模型', '分', '几', '类', ':', '波', '形', '生成', '直接', '合成', '声音', ',', '谱', '图', '生成', '转', '波', '形', ',', '基于', '单元', '的', '合成', '按', '片段', '拼', '接', '。', '']

异步流式输出

相对于同步,异步的输出模式往往更符合期待,我们尝试一下一个简单的demo
由于篇幅问题,无法给出完整的代码,但是主要逻辑已经留下。

asyncio.run(main_func()) #必须使用协程启动,否则主函数会不顾及协程的进度,直接终结
async def main_func(): #由于内部的await只能存在于异步函数中
	llm = Ollama(
        model="qwen2.5:14b", callback_manager=CallbackManager([StreamingStdOutCallbackHandler()]),
        streaming=True,
    )#注意,此处打开流式输出模式
	chains = chat_prompt | llm | output_parser #此处依旧加入了输出转Str方便我们后面出处理
	    while True:
        current_data = time.time()
        flag, last_time = check_file_changed(in_dir, last_time)
        time.sleep(0.5)
        if current_data >= end_time:
            break
        elif flag:
            print("The file has been changed!!!")
            current_text = text_load(in_dir)
            async for text in streaming_loop_asynch(chains, current_text):#异步生成器,将每次获取一个迭代,实现流式。
                print(text)
async def streaming_loop_asynch(llm, prompt):
    chunks = []
    async for chunk in llm.astream(prompt):
        chunks.append(chunk)
        print(chunk, end="|", flush=True)
        await asyncio.sleep(0.5)#设置默认等待时间,但其实无所谓的
        yield chunk #生成器,每次会顺着上次的结束点继续生成。

进阶功能与实现示例

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值