大型语言模型(LLM)使用 最近稍微折腾了一下 LLM,记录一下相关的一些内容📝:
API 调用 OpenAI 需要花💰直接调用的 API 通常情况下采用的是这一种调用方式
👴🚪 正在用的是 柏拉图AI ,价格可以接受,模型也多
Python3 调用脚本示例(Chat):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 from openai import OpenAIdef chat_with_openai ( prompt: str , model: str = "gpt-4o-mini" , api_key: str = "api_key" , base_url: str = "https://api.bltcy.ai/v1" , system_message: str = None , max_tokens: int = 10240 , temperature: float = 0.7 , stream: bool = False , ) -> str : """ 使用 OpenAI 的 Chat API 进行对话生成。 参数: prompt (str): 用户输入的提示文本 model (str): 要调用的模型名称 api_key (str): 替换成自己的 API 的密钥 base_url (str): 使用第三方平台时替换成对应的 API URL (找对应的说明文档) system_message (str): 可选的系统消息,用于设置对话的上下文或行为 max_tokens (int): 生成文本的最大长度,这里默认为 10240,单位是 token temperature (float): 控制生成文本的随机性,这里默认为 0.7。该数值越大,生成的文本随机性越大 stream (bool): 是否启用流式输出,这里默认为 False 返回: str: 生成的文本内容。如果启用流式输出,返回生成器的内容。 """ try : client = OpenAI(api_key=api_key, base_url=base_url) messages = [] if system_message: messages.append({"role" : "system" , "content" : system_message}) messages.append({"role" : "user" , "content" : prompt}) response = client.chat.completions.create( model=model, messages=messages, max_tokens=max_tokens, temperature=temperature, stream=stream, ) if stream: def generate (): for chunk in response: if chunk.choices[0 ].delta.content: yield chunk.choices[0 ].delta.content return generate() else : return response.choices[0 ].message.content except Exception as e: print (f"An error occurred: {e} " ) return None
更多详细的 API 调用说明可以前往 📦 openai-python 仓库查看 api.md
Ollama 如果服务器端是通过 Ollama 搭建的,那么需要下面的方式进行调用。(本地部署搭建 Ollama 的过程在后面进行介绍)
Python3 脚本示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 from ollama import Clientdef chat_with_ollama ( prompt: str , model: str = "deepseek-coder-v2:latest" , host: str = "http://192.168.155.8:11434" , system_message: str = None , max_tokens: int = 10240 , temperature: float = 0.7 , stream: bool = False , ) -> str : """ 使用 Ollama Client 进行对话生成。 参数: prompt (str): 用户输入的提示文本 model (str): 自行指定要使用的模型名称 host (str): Ollama 服务的主机地址,需要指定为对应的 Ollama 服务器地址 system_message (str): 可选的系统消息,用于设置对话的上下文或行为 max_tokens (int): 生成文本的最大长度,默认为 10240 temperature (float): 控制生成文本的随机性,默认为 0.7 stream (bool): 是否启用流式输出,默认为 False 返回: str: 生成的文本内容。如果启用流式输出,返回生成器的内容 """ try : client = Client(host=host) messages = [] if system_message: messages.append({"role" : "system" , "content" : system_message}) messages.append({"role" : "user" , "content" : prompt}) response = client.chat( model=model, messages=messages, options={ "num_ctx" : max_tokens, "temperature" : temperature, }, stream=stream, ) if stream: def generate (): for chunk in response: yield chunk["message" ]["content" ] return generate() else : return response["message" ]["content" ] except Exception as e: print (f"An error occurred: {e} " ) return None def generate_with_ollama ( prompt: str , model: str = "deepseek-coder-v2:latest" , host: str = "http://192.168.155.8:11434" , max_tokens: int = 10240 , ) -> str : """ 使用 Ollama Client 进行文本生成(非对话模式)。 参数: prompt (str): 输入的提示文本。 model (str): 自行指定要使用的模型名称 host (str): Ollama 服务的主机地址,需要指定为对应的 Ollama 服务器地址 max_tokens (int): 生成文本的最大长度 返回: str: 生成的文本内容 """ client = Client(host=host) response = client.generate( model=model, prompt=prompt, options={"num_ctx" : max_tokens}, ) return response["response" ]
更多详细的 API 调用说明可以前往 📦 ollama-python 仓库查看 api.md
本地部署 仅记录 Linux 下的 Ollama 部署流程:
🏝️ 部署环境
软件环境:
操作系统:Ubuntu 22.04 LTS
显卡驱动:565.57.01
CUDA 版本:12.7
硬件配置:
Intel(R) Xeon(R) CPU E5-2690 v4 @ 2.60GHz
NVIDIA GeForce RTX 3080
下载安装 Linux 系统下直接执行下述命令安装 Ollama:
1 curl -fsSL https://ollama.com/install.sh | sh
其他操作系统从官网直接下载安装包安装即可:https://ollama.com/download
拉取模型 安装完毕后即可从 ollama.com 中搜索并拉取需要的模型,以 deepseek-r1
为例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 # 拉取并加载运行 deepseek-r1:8b 模型 $ ollama run deepseek-r1:8b pulling manifest pulling 6340dc3229b0... 100% ▕██████████████████████████████████████████████████████████████████▏ 4.9 GB pulling 369ca498f347... 100% ▕██████████████████████████████████████████████████████████████████▏ 387 B pulling 6e4c38e1172f... 100% ▕██████████████████████████████████████████████████████████████████▏ 1.1 KB pulling f4d24e9138dd... 100% ▕██████████████████████████████████████████████████████████████████▏ 148 B pulling 0cb05c6e4e02... 100% ▕██████████████████████████████████████████████████████████████████▏ 487 B verifying sha256 digest writing manifest success > >> 你是谁? <think> </think> 您好!我是由中国的深度求索(DeepSeek)公司开发的智能助手DeepSeek-R1。如您有任何任何问题,我会尽我所能为您提供帮助。 > >> Send a message (/? for help )
通过 ollama run
命令运行的模型将在前台执行,执行 /exit
可以退出前台运行。
至于大模型参数量的选择,可以参考 这篇博客
在模型拉取之后可以使用 ollama list
查看已存在的模型,并且可以通过 11434
端口对已存在的模型进行 API 调用(无需处于前台执行),调用方法已在前面介绍过。但默认情况下仅可通过本地访问 11434
端口,如果需要全局监听则需要更改 Ollama 服务配置,在 [Service]
模块下增加 Environment="OLLAMA_HOST=0.0.0.0"
,保存后重载服务配置生效。
修改 /etc/systemd/system/ollama.service
配置文件:
1 2 3 4 5 6 7 8 9 10 [Unit] Description =Ollama ServiceAfter =network-on line.target[Service] ...... 原来的内容保持不动,在下面添加即可 Environment ="OLLAMA_HOST=0.0.0.0" [Install] WantedBy =default.target
重载服务:
1 2 sudo systemctl daemon-reload sudo systemctl restart ollama
Web UI 平台搭建 如果需要一个类似于 ChatGPT 那样的 Web 访问平台,可以搭建 Open WebUI 、Lobe Chat 、AnyThing LLM 等。以 Open WebUI 为例,在 Ollama 服务器上使用 Docker 搭建:
1 docker run -d -p 3000:8080 --add-host=host.docker.internal:host-gateway -v open-webui:/app/backend/data --name open-webui --restart always ghcr.io/open-webui/open-webui:main
具体选用的安装方式最好还是根据使用需求,参考各仓库的 README 文档进行部署。
微调 在一些研究或工作当中,现有的通用 LLM 可能在一些专用领域中表现欠佳,或者需要为模型提供一些专用的知识库,因此通常考虑对合适的模型进行微调,以实现专用知识问答等需求。
unsloth unsloth 是一个专注于高效微调的框架,旨在帮助用户快速、低成本地对大语言模型进行定制化训练。它支持多种流行的开源模型,如 LLaMA3.2、Gemma2、Qwen2.5 等,并且针对这些模型进行了深度优化,显著减少了微调所需的时间和显存占用。通过 unsloth,用户可以在消费级 GPU 上完成微调任务,而无需依赖昂贵的硬件设备。
全部支持的模型可以从 HuggingFace 中找到,各自都带有对应的 JupyterNotebook 代码,可以直接在 Colab 使用免费的 T4 进行测试。
已测试 Qwen2.5-7B-Instruct 可以在 GeForce RTX 3080 上进行微调
⚠️ 注意事项 由于脚本执行时会从 HuggingFace 拉取大量的数据,在本地执行的时候最好先添加下面的代码,修改环境变量来指定 HuggingFace 的镜像源用于加速下载
1 2 import osos.environ["HF_ENDPOINT" ] = "https://hf-mirror.com"
接下来以 Qwen2.5-7B-Instruct 为例简单记录一下微调过程:
unsloth 的环境配置直接参考其 Github 仓库中的安装步骤即可
在 README 文档中找到 Qwen 2.5 conversational style notebook ,即 Qwen 2.5 Conversational + Unsloth 2x faster finetuning.ipynb
,直接下载到本地
根据实际情况修改开头部分的模型选择:
1 2 3 4 5 6 7 8 9 10 11 model, tokenizer = FastLanguageModel.from_pretrained( model_name = "unsloth/Qwen2.5-7B-Instruct" , max_seq_length = max_seq_length, dtype = dtype, load_in_4bit = load_in_4bit, )
绝大部分内容保持默认即可,如果需要使用自己构建的训练数据集,需要改动 load_dataset()
的内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 from unsloth.chat_templates import get_chat_templatetokenizer = get_chat_template( tokenizer, chat_template = "qwen-2.5" , ) def formatting_prompts_func (examples ): convos = examples["conversations" ] texts = [tokenizer.apply_chat_template(convo, tokenize = False , add_generation_prompt = False ) for convo in convos] return { "text" : texts, } pass from datasets import load_datasetdataset = load_dataset("mlabonne/FineTome-100k" , split = "train" )
📒 一点建议
自行构建微调数据集时可以先在 huggingface 中找到原本加载的数据集,参考其内容格式进行构建
具体的代码含义直接 AI 解释即可
参数设置,这一步可以根据实际需求修改训练参数(重点修改 num_train_epochs
或 max_steps
,如果希望模型在完整的数据集上训练固定的次数,可以使用 num_train_epochs
,如果更关注训练的步数(例如,调试或小规模实验),可以使用 max_steps
)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 from trl import SFTTrainerfrom transformers import TrainingArguments, DataCollatorForSeq2Seqfrom unsloth import is_bfloat16_supportedtrainer = SFTTrainer( model = model, tokenizer = tokenizer, train_dataset = dataset, dataset_text_field = "text" , max_seq_length = max_seq_length, data_collator = DataCollatorForSeq2Seq(tokenizer = tokenizer), dataset_num_proc = 2 , packing = False , args = TrainingArguments( per_device_train_batch_size = 2 , gradient_accumulation_steps = 4 , warmup_steps = 5 , num_train_epochs = 1 , learning_rate = 2e-4 , fp16 = not is_bfloat16_supported(), bf16 = is_bfloat16_supported(), logging_steps = 1 , optim = "adamw_8bit" , weight_decay = 0.01 , lr_scheduler_type = "linear" , seed = 3407 , output_dir = "outputs" , report_to = "none" , ), )
模型训练,trainer.train()
这一步执行后慢慢等待训练完成即可
完成训练后的内容是测试微调后的模型,略过这一步
保存模型,这一步可以将微调后的模型进行保存(存储到 huggingface 或者本地,也可导出 GGUF,支持导入到 Ollama 中)
直接根据实际需求找到对应的行将 if False
该为 True
即可
例如导出为 Q8_0
:
1 2 if True : model.save_pretrained_gguf("path_to_save_model" , tokenizer,)
至于不同的量化类型可以参考这两篇博客进行选择:AI 模型量化格式介绍 , 为 llama.cpp 选择理想的量化类型
不过简单来说,如果配置足够,直接选用 Q8_0
就好
顺带引用一下第二篇博客里的图片:
background Layer 1 最差模型 有潜力 最佳模型 低优先级 Q8_0 Q6_K Q5_K_M Q5_1 Q5_K_S Q5_0 Q4_1 Q4_K_M Q4_K_S Q4_0 Q3_K_L Q3_K_M 体积小 体积大 困惑度小 困惑度大 大小与困惑度变化对比
导入到 Ollama 中运行微调后的模型,这一步直接使用上一步导出的模型文件中自带的 Modelfile 即可
1 2 3 4 # 切换到上一步导出的模型目录 cd path_to_save_model # 导入 ollama create <model_name> -f ./Modelfile
不使用框架 如果 unsloth 尚未支持需要微调的模型,可以在 开源大模型食用指南 中尝试找一找微调指南