
FastChat Embedding 实战指南用 Vicuna 完成语义搜索、文本相似度与情感分类评测【免费下载链接】FastChatAn open platform for training, serving, and evaluating large language models. Release repo for Vicuna and Chatbot Arena.项目地址: https://gitcode.com/GitHub_Trending/fa/FastChat本指南基于 FastChat 仓库中的 playground/test_embedding/README.md 与配套测试脚本系统讲解如何把 Vicuna以及对照的 OpenAI 文本向量模型的 Embedding 能力落地到三大机器学习任务上评测文本相似度、构建分类器、进行语义搜索。读完本文你将掌握 FastChat 的 OpenAI 兼容/v1/embeddings接口的调用方式、三份测试脚本的完整用法与数据集准备流程并能理解每个脚本背后由 model_worker.py 提供的向量化实现原理。一、背景FastChat 把最后一层隐藏状态变成通用机器学习输入FastChat 的核心是训练、服务与评测大语言模型的开放平台。除了对话生成它还通过 OpenAI 兼容接口暴露了 Embedding 能力——在 openai_api_server.py 中注册了/v1/embeddings端点。这意味着你可以像使用text-embedding-ada-002一样把本地部署的 Vicuna 当作向量化引擎为下游的相似度计算、分类、检索等经典机器学习任务提供特征输入。仓库专门在playground/test_embedding目录下提供了三份可直接运行的对比实验脚本用来回答一个问题开源 Vicuna 的 Embedding 与 OpenAI 专用文本向量模型相比在标准任务上到底有多大差距。三份脚本分别是脚本核心任务对应小节test_sentence_similarity.py句子级文本相似度三、文本相似度评测test_classification.py文本分类情感/评分预测四、文本分类实战test_semantic_search.py语义搜索/相关性检索五、语义搜索实战二、环境准备数据集与运行方式1. 数据集下载三个实验都使用同一份公开数据集Amazon Fine Food Reviews亚马逊食品评论其中包含评论的标题Summary、正文Text与 1~5 星评分Score。按 README 的说明需自行下载该数据集并把 CSV 文件放到脚本所在目录文件名固定为amazon_fine_food_review.csv。三份脚本都在入口处做了存在性校验例如 test_classification.pyinput_datapath amazon_fine_food_review.csv if not os.path.exists(input_datapath): raise Exception( fPlease download data from: https://www.kaggle.com/datasets/snap/amazon-fine-food-reviews )也就是说若 CSV 缺失脚本会直接报错终止而非静默运行确保实验前提明确。2. 需要两把钥匙本地 Vicuna OpenAI API KeyREADME 明确指出运行这些测试需要 OpenAI API Key 用于对照。原因是三份脚本都把三种模型拉到了同一评测基准上vicuna-7b-v1.1/vicuna-7b-v1.5由本地 FastChat 服务提供的开源模型向量text-similarity-ada-001OpenAI 早期的相似度模型deprecatedtext-embedding-ada-002OpenAI 广泛使用的通用 Embedding 模型。这里要注意区分两类模型在不同脚本中的角色本地 Vicuna是通过 FastChat 的 OpenAI 兼容服务访问的走 HTTP 请求ada 系列是通过openai官方 Python 库访问的走官方云端 API。三份脚本的get_embedding_from_api函数都用同一个技巧做了路由分流以 test_sentence_similarity.py 为例def get_embedding_from_api(word, modelvicuna-7b-v1.5): if ada in model: resp openai.Embedding.create( modelmodel, inputword, ) embedding np.array(resp[data][0][embedding]) return embedding url http://localhost:8000/v1/embeddings headers {Content-Type: application/json} data json.dumps({model: model, input: word}) response requests.post(url, headersheaders, datadata) if response.status_code 200: embedding np.array(response.json()[data][0][embedding]) return embedding else: print(fError: {response.status_code} - {response.text}) return None关键判定逻辑是if ada in model模型名含ada就调用 OpenAI 官方接口否则一律走http://localhost:8000/v1/embeddings。这个默认地址正是 docs/openai_api.md 中演示的本地端点curl http://localhost:8000/v1/embeddings \ -H Content-Type: application/json \ -d { model: vicuna-7b-v1.5, input: Hello world! }3. 启动本地服务并运行脚本按照 README实验需先以 FastChat 的标准三步曲启动服务Controller → Model Worker → OpenAI API Server具体流程可参考 docs/openai_api.md 与 docs/server_arch.md。服务就绪后在playground/test_embedding目录下直接运行cd playground/test_embedding python3 test_classification.pyREADME 描述脚本的运行结果是基于vicuna-7b、text-similarity-ada-001、text-embedding-ada-002分别训练分类器并报告各自的准确率accuracy。其余两脚本同理将脚本名替换为test_sentence_similarity.py或test_semantic_search.py即可。依赖提醒三个脚本分别依赖numpy、pandas、requests、openai、scipy分类脚本还额外依赖scikit-learnsklearn.ensemble.RandomForestClassifier与sklearn.model_selection.train_test_split运行前请确保这些包已安装。4. 数据的预处理管线三份脚本共享同一套数据清洗逻辑create_embedding_data_frame值得展开说明def create_embedding_data_frame(data_path, model, max_tokens500): df pd.read_csv(data_path, index_col0) df df[[Time, ProductId, UserId, Score, Summary, Text]] df df.dropna() df[combined] ( Title: df.Summary.str.strip() ; Content: df.Text.str.strip() ) top_n 1000 df df.sort_values(Time).tail(top_n * 2) df.drop(Time, axis1, inplaceTrue) df[n_tokens] df.combined.apply(lambda x: len(x)) df df[df.n_tokens max_tokens].tail(top_n) df[embedding] df.combined.apply(lambda x: get_embedding_from_api(x, model)) return df字段裁剪与去空只保留Time/ProductId/UserId/Score/Summary/Text六列并dropna()清除缺失行文本拼接把评论标题与正文拼成Title: ...; Content: ...的单一文本串作为向量化的输入单元语义信息比单独用标题更完整时间窗口采样按Time排序后取最近1000条先截top_n * 2 2000条再过滤保证样本不过时长度过滤以字符数近似 token 数n_tokens len(x)超过max_tokens500的长评论被剔除——这避免了超出模型上下文窗口导致请求失败批量向量化对每个样本调用get_embedding_from_api生成向量并存入新列。注意这里用的是len()按字符近似计 token并非精确 tokenizer 计数因此max_tokens实际是最大字符数的宽松约束。三、文本相似度评测test_sentence_similarity.py这是最直观的一课判断两段文本在语义上像不像。脚本构造了四句精心设计的话texts [ The quick brown fox, The quick brown dog, The fast brown fox, A completely different sentence, ]然后对每句话分别用三种模型取向量再两两计算余弦相似度test_sentence_similarity.pydef print_cosine_similarity(embeddings, texts): for i in range(len(texts)): for j in range(i 1, len(texts)): sim cosine_similarity(embeddings[texts[i]], embeddings[texts[j]]) print(fCosine similarity between {texts[i]} and {texts[j]}: {sim:.2f})余弦相似度的实现直接用 scipy 的距离函数换算def cosine_similarity(vec1, vec2): return 1 - cosine(vec1, vec2)对照实验的预期结论在文本设计上已经埋好The quick brown foxvsThe quick brown dog仅替换一个词fox→dog共享 3/4 词汇相似度应很高The quick brown foxvsThe fast brown fox同义改写quick→fast体现语义等价而词面不同能否被抓住The quick brown foxvsA completely different sentence完全无关相似度应接近 0。脚本依次打印Vicuna-7B:、text-similarity-ada-001:、text-embedding-ada-002:三组结果默认模型为vicuna-7b-v1.5。运行后你可以直观比较对于同义替换这种考验语义建模能力的 case本地 Vicuna 与 OpenAI 专用向量模型谁更接近人类直觉。这是判断模型 Embedding 质量最轻量的冒烟测试。四、文本分类实战用 Embedding 训练评分预测器test_classification.pyEmbedding 最常见的工程用途之一是把自由文本变成固定维度的数值特征再喂给传统机器学习模型做分类。test_classification.py 把它落到了一个真实业务问题上根据亚马逊食品评论的文本内容预测用户打了 1~5 星的哪一个评分五分类情感分析。1. 特征与标签准备脚本复用前述的create_embedding_data_framemax_tokens500把每条评论转成一个向量作为特征X评论自带的Score1~5作为标签y。2. 训练随机森林并评估训练函数使用 scikit-learndef train_random_forest(df): X_train, X_test, y_train, y_test train_test_split( list(df.embedding.values), df.Score, test_size0.2, random_state42 ) clf RandomForestClassifier(n_estimators100) clf.fit(X_train, y_train) preds clf.predict(X_test) report classification_report(y_test, preds) accuracy accuracy_score(y_test, preds) return clf, accuracy, report划分train_test_split以 80%/20% 切分random_state42固定随机种子保证三组模型在完全相同的训练/测试划分上比较结论公平模型RandomForestClassifier(n_estimators100)100 棵树。之所以选随机森林是因为它是天然接受每样本一个向量这类表格化特征的非线性模型无需任何文本层面的改动指标同时输出classification_report含精确率/召回率/F1与整体accuracy_score。3. 三种模型的公平对比主流程按顺序跑三遍并打印准确率test_classification.pydf create_embedding_data_frame(input_datapath, vicuna-7b-v1.1) clf, accuracy, report train_random_forest(df) print(fVicuna-7b-v1.1 accuracy:{accuracy}) df create_embedding_data_frame(input_datapath, text-similarity-ada-001) clf, accuracy, report train_random_forest(df) print(ftext-similarity-ada-001 accuracy:{accuracy}) df create_embedding_data_frame(input_datapath, text-embedding-ada-002) clf, accuracy, report train_random_forest(df) print(ftext-embedding-ada-002 accuracy:{accuracy})注意该脚本默认使用vicuna-7b-v1.1与另两份脚本的v1.5略有差异说明向量接口对各版本模型通用。由于划分、数据、分类器全部固定唯一变量就是特征来源——准确率差异即可归因于三种 Embedding 模型对评论文本语义的编码质量。这也是 README 所述报告每个分类器准确率的完整含义。你可以把这套模式迁移到任意自有标注数据集上作为选型本地开源模型 vs OpenAI 向量模型的基准流程。五、语义搜索实战把向量当检索引擎test_semantic_search.py第三份脚本演示了零训练的语义检索给定一段产品描述/用户需求在 1000 条评论中找出语义最相关的几条。test_semantic_search.py 的核心搜索函数def search_reviews(df, product_description, n3, pprintFalse, modelvicuna-7b-v1.1): product_embedding get_embedding_from_api(product_description, modelmodel) df[similarity] df.embedding.apply( lambda x: cosine_similarity(x, product_embedding) ) results ( df.sort_values(similarity, ascendingFalse) .head(n) .combined.str.replace(Title: , ) .str.replace(; Content:, : ) ) if pprint: for r in results: print(r[:200]) print() return results工作流非常清晰查询向量化对查询文本调用同一个get_embedding_from_api注意必须使用与语料相同的模型保证向量在同一语义空间批量相似度用df.embedding.apply把每条评论向量与查询向量算余弦相似度cosine_similarity内部同样是1 - scipy.spatial.distance.cosine排序取 top-n按相似度降序排序并取前n条再把展示文本还原为Title: ...: Content...的可读格式。脚本内置了三个不同维度的查询print_model_searchdelicious beans面向口味/食材的查询应命中好评食品评论whole wheat pasta另一类具体品类查询bad delivery**负面体验物流**查询考察模型能否抓住吐槽类语义而非字面词汇。每个查询对三种模型各跑一遍n5即各返回 5 条最相关评论因此你在输出中能直接横向对比同样是搜bad deliveryVicuna 检索出的评论是否真的在抱怨配送还是被字面的delivery干扰。这就是 Embedding 检索与传统关键词匹配的本质差异——召回靠语义相关而非词汇重合。六、原理纵深本地 Vicuna 的 Embedding 到底怎么算出来的README 只给出了脚本用法而真正支撑Vicuna 可当 Embedding 引擎这一事实的是服务端 model_worker.py 中的实现。理解它有助于解释实验中可能出现的现象例如为何要设max_tokens、为何 ada 与 Vicuna 的向量维度不同。1. 请求链路脚本发往http://localhost:8000/v1/embeddings后openai_api_server.py 会校验模型、将输入按WORKER_API_EMBEDDING_BATCH_SIZE默认 4定义于 constants.py分批然后经get_worker_address找到持有该模型的 worker转发到其/worker_get_embeddings端点见 base_model_worker.py 与 multi_model_worker.py 的同名路由最终落在ModelWorker.get_embeddings。2. 池化Pooling策略LLM 输出的每个 token 都有一个隐藏状态必须聚合为一句话一个向量。从 model_worker.py 的__process_embed_chunk可见两种策略if hasattr(self.model, use_cls_pooling) and self.model.use_cls_pooling: sum_embeddings data[:, 0] # CLS 池化取序列首 token else: mask attention_mask.unsqueeze(-1).expand(data.size()).float() masked_embeddings data * mask sum_embeddings torch.sum(masked_embeddings, dim1) # 均值池化按 mask 求和对 BERT 类模型支持use_cls_pooling取[CLS]位置的向量对 llama/chatglm 等通用 LM则用 attention mask 屏蔽 padding 后对最后一层隐藏状态求和再除以有效 token 数做平均见同文件 L221-L226。3. 长文本的分块处理与归一化当embed_in_truncate未开启时长输入会按context_len切成多个 chunk 分别过模型、再把各 chunk 的结果按 token 数加权合并model_worker.py最后统一做 L2 归一化normalized_embeddings F.normalize(embedding, p2, dim1)归一化后向量长度恒为 1余弦相似度就等于内积检索排序因此更稳定。worker 端也支持encoding_formatbase64以减少传输开销见__encode_base64。这正对应服务端EmbeddingsRequest中可选的encoding_format字段openai_api_protocol.py响应体也复用了 OpenAI 风格的EmbeddingsResponse。4. 服务端批处理与 OOM 规避向量化长文本比对话生成更容易触发显存不足OOM因为整批样本都要前向传播。服务端已内置应对手段create_embeddings会按WORKER_API_EMBEDDING_BATCH_SIZE分批请求 workeropenai_api_server.py而该值可通过环境变量调小正如 docs/openai_api.md 所提示export FASTCHAT_WORKER_API_EMBEDDING_BATCH_SIZE1若请求超时默认 100 秒见 constants.py也可调大FASTCHAT_WORKER_API_TIMEOUT。在 playground 脚本侧max_tokens500的预处理则从源头把单条输入限制在可控长度内与服务端能力形成呼应。七、把实验迁移到自己的任务上三份脚本的真正价值在于模式可复用。结合本仓库的源码结构你可以总结出四条迁移经验Embedding 服务化即可替换脚本中模型名含 ada 走官方、否则走本地 8000 端口的分流说明只要 FastChat 服务在跑任何模型换--model-path与--model-names重启 worker 即可都能无缝接入同一套评测代码——把get_embedding_from_api的默认模型名与create_embedding_data_frame的model实参换掉即可切换评测对象。向量特征可进任意 sklearn 模型分类样例展示的train_test_split RandomForestClassifier是通用范式换成逻辑回归、SVM 或 XGBoost 亦无不可Embedding 只是把文本问题降维成了表格问题。语义检索无需训练search_reviews这种查询向量 余弦相似度 top-n 排序的三段式配上FAISS一类近似最近邻库即可扩到百万级语料小型 demo 里 pandas sort_values已足够直观。对比实验要控制变量三脚本都刻意让数据采样、划分种子、分类器完全一致仅替换向量来源——这是让模型对比结论可信的关键纪律。最后再次提醒运行前提启动完整的 FastChat 服务Controller/Model Worker/OpenAI API Server下载amazon_fine_food_review.csv至playground/test_embedding目录配置好 OpenAI API Key随后即可依次运行三份脚本用同一份数据回答开源 Vicuna 的 Embedding 能否胜任相似度、分类与检索这一选型问题。更多服务端部署细节可继续阅读 docs/openai_api.md、docs/server_arch.md 与 docs/langchain_integration.md。【免费下载链接】FastChatAn open platform for training, serving, and evaluating large language models. Release repo for Vicuna and Chatbot Arena.项目地址: https://gitcode.com/GitHub_Trending/fa/FastChat创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考