【嵌入模型与向量数据库】

目录

一、什么是向量?

二、为什么需要向量数据库?

三、向量数据库的特点

四、常见的向量数据库产品

FAISS 支持的索引类型 vs 相似度

五、常见向量相似度方法对比

六、应该用哪种

七、向量数据库的核心逻辑

🔍 示例任务:查找与这句话最相似的一句话

八、图示:向量空间中的相似度搜索

九、实际案例:文本语义检索

十、实际案例:图像搜索

十一、总结图:向量数据库流程

十二、 faiss向量数据代码用例

说明

文件结构

 documents.txt

main.py(简化版)

运行结果


向量数据库(Vector Database)是一种专门用于存储、管理和检索高维向量数据的数据库系统。它的核心作用是实现相似度搜索(Similarity Search),即在海量数据中快速找到“最相似”的数据项。


一、什么是向量?

在机器学习和人工智能中,向量是一种用来表示数据的数学结构。比如:

  • 一张图片可以被编码成一个128维的向量。

  • 一段文本可以通过模型(如BERT)转换成768维的向量。

  • 用户的兴趣或商品的特征也可以表示为向量。

这些向量通常来源于神经网络模型,称为“嵌入向量(embedding)”。


二、为什么需要向量数据库?

传统数据库适合处理结构化数据(如数字、字符串等),而不适合处理向量的“相似性检索”。向量数据库的优势在于可以支持如下需求:

  • 检索与某段文本语义相似的内容(如ChatGPT的知识搜索)

  • 找到与用户行为相似的商品或视频(推荐系统)

  • 查找长相相似的人脸图像(图像识别)

  • 在安全监控中匹配相似的车牌或目标(目标识别)


三、向量数据库的特点

特点描述
高维向量支持支持数十到上千维的向量存储与计算
相似度检索支持基于余弦相似度、欧氏距离、点积等方式的Top-K搜索
近似最近邻搜索(ANN)使用高效算法(如 HNSW、IVF、PQ)实现“近似而快速”的搜索
可扩展性能够处理上亿甚至上百亿条向量数据
多模态支持支持图像、文本、音频等多种模态的向量嵌入


四、常见的向量数据库产品

名称特点
FAISS(Meta)高性能向量搜索库,适合本地使用
Milvus开源,分布式,支持亿级向量,适合工业部署
Weaviate支持文本搜索和语义索引,内置向量生成
Pinecone云原生,面向生产级应用
Qdrant支持高效过滤器和payload数据的检索

FAISS 支持的索引类型 vs 相似度

FAISS 索引类型支持相似度方式是否需归一化
IndexFlatL2欧氏距离❌ 否
IndexFlatIP内积(近似余弦)✅ 是(手动)
IndexFlatCosine✅ 余弦相似度✅ 自动归一化(新版本才支持)

  • FAISS: Meta 开源的向量检索引擎 https://github.com/facebookresearch/faiss
  • Pinecone: 商用向量数据库,只有云服务 The vector database to build knowledgeable AI | Pinecone
  • Milvus: 开源向量数据库,同时有云服务 Milvus | High-Performance Vector Database Built for Scale
  • Weaviate: 开源向量数据库,同时有云服务 The AI-native database developers love | Weaviate
  • Qdrant: 开源向量数据库,同时有云服务 Qdrant - Vector Database - Qdrant
  • PGVector: Postgres 的开源向量检索引擎 https://github.com/pgvector/pgvector
  • RediSearch: Redis 的开源向量检索引擎 https://github.com/RediSearch/RediSearch
  • ElasticSearch 也支持向量检索 Elasticsearch vector search - highly relevant, lightning fast search | Elastic

五、常见向量相似度方法对比

方法名称公式(向量 A 和 B)取值范围越小越相似?特点说明
欧氏距离 (L2)[0, +∞)✅ 是距离越小越相似。对向量长度敏感。
余弦相似度[-1, 1]❌ 否越接近 1 越相似。方向相近即可,不管长度。
内积 (dot product)任意实数❌ 否通常需要归一化后使用,变成余弦相似度。


六、应该用哪种

场景推荐相似度类型理由
文本检索 / 语义搜索余弦相似度 or 内积(需归一化)语义相似的句子方向一致,即便长度不同也应视为相似。
数值空间距离计算欧氏距离(L2)更注重“几何距离”本身。
图像、传感器数据L2 / 内积嵌入空间常是连续向量域,L2 更合适。

代码示例

import numpy as np# 假设有两个向量
vec1 = np.array([0.1, 0.3, 0.5])
vec2 = np.array([0.2, 0.1, 0.7])# 欧氏距离
euclidean = np.linalg.norm(vec1 - vec2)# 曼哈顿距离
manhattan = np.sum(np.abs(vec1 - vec2))# 余弦相似度
cosine = np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2))print(f"欧氏距离: {euclidean:.4f}")
print(f"曼哈顿距离: {manhattan:.4f}")
print(f"余弦相似度: {cosine:.4f}")

运行结果

欧氏距离: 0.3000
曼哈顿距离: 0.5000
余弦相似度: 0.9201


七、向量数据库的核心逻辑

🔍 示例任务:查找与这句话最相似的一句话

🟢 查询语句:

“我今天想去看电影。”

被模型(如 BERT)转换成一个 768 维向量:
[0.12, -0.34, 0.56, ..., 0.87]

🗂 向量数据库中预存了大量句子的向量,比如:

原始句子向量表示(768维)
“晚上看个电影放松一下吧。”[0.13, -0.33, 0.57, ..., 0.88]
“我今天不太想出门。”[0.01, -0.55, 0.24, ..., 0.39]
“今天天气很好。”[0.45, 0.22, 0.18, ..., 0.72]

📌 向量数据库通过余弦相似度等算法,找出最相似的向量(Top-K),再返回对应的句子。


八、图示:向量空间中的相似度搜索

想象每个句子被映射到一个三维空间中的点(实际是高维空间):


🧲 目标是:找到距离查询点最近的几个点 —— 这就是向量数据库做的事!


九、实际案例:文本语义检索

你构建了一个问答系统,用户输入:

“怎么注册公司的营业执照?”

系统会将这个问题转为向量,然后在知识库中查找语义最接近的答案,比如:

  • “如何办理工商注册?”

  • “注册公司需要准备哪些资料?”

  • “去哪个地方办营业执照?”

向量数据库会返回这些“语义相似”的文本,而不只是关键词匹配。

🧠 这就是语义搜索 vs 关键词搜索的区别。


十、实际案例:图像搜索

你上传一张猫的照片,系统会在数据库中返回类似的图片:

  • 🐱 颜色相近的猫

  • 🐈 姿势相似的猫

  • 🐾 背景相近的猫图

原因是:图像也可以转成向量,向量数据库进行相似度查找


十一、总结图:向量数据库流程

   原始数据(文本/图片/音频)↓向量模型生成 embedding↓向量入库(Milvus, FAISS, Pinecone等)↓用户输入查询 → 同样转换成向量↓在向量空间中找最近的K个邻居(ANN)↓返回原始内容(文本、图片、视频等)

十二、 faiss向量数据代码用例

说明

1、选用向量模型:阿里百炼的文本向量模型(text-embedding-v1);

2、运行条件:需要有百炼控制台的APIkey;

3、查看(选择)其它向量模型:百炼控制台;

该图是百炼提供的3种文本向量模型 


文件结构

semantic_search_demo/
├── main.py              # 主程序
├── documents.txt        # 示例语料库(你要搜索的内容)
├── requirements.txt     # 依赖库


 documents.txt

这个作为知识库示例

注册公司需要准备身份证、注册地址、公司章程等材料。
营业执照由工商局颁发,需要填写申请表。
税务登记是注册公司的后续步骤。
开公司银行账户需要营业执照和法人身份证。
你可以在线申请营业执照。


main.py(简化版)

import faiss
import dashscope
import os
import numpy as np
from tqdm import tqdm# 设置 API KEY(你也可以改为用环境变量)
dashscope.api_key = os.getenv("DASHSCOPE_API_KEY")# 获取当前脚本所在目录的绝对路径
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
DOC_PATH = os.path.join(BASE_DIR, "documents.txt")# 载入文档
if not os.path.exists(DOC_PATH):raise FileNotFoundError(f"未找到文件:{DOC_PATH}")with open(DOC_PATH, "r", encoding="utf-8") as f:docs = [line.strip() for line in f.readlines() if line.strip()]# 使用阿里百炼嵌入模型
def get_embedding(text):rsp = dashscope.TextEmbedding.call(model="text-embedding-v1",input=text)if rsp.status_code == 200:return rsp.output['embeddings'][0]['embedding']else:raise ValueError(f"❌ 嵌入失败: {rsp.message}")# 生成文档向量
print("🔍 正在生成文档向量...")
doc_embeddings = [get_embedding(doc) for doc in tqdm(docs)]# 建立 FAISS 索引
dim = len(doc_embeddings[0])
index = faiss.IndexFlatL2(dim)
index.add(np.array(doc_embeddings).astype("float32"))# 查询函数
def search(query, top_k=3):q_embedding = get_embedding(query)D, I = index.search(np.array([q_embedding]).astype("float32"), top_k)return [(docs[i], D[0][j]) for j, i in enumerate(I[0])]# 主循环
if __name__ == "__main__":while True:q = input("\n请输入查询(输入 'exit' 退出):\n> ")if q.lower() == "exit":breakresults = search(q)print("\n🔍 最相似的段落:")for i, (text, score) in enumerate(results):print(f"{i+1}. {text}  (距离:{score:.4f})")

运行结果

🔍 正在生成文档向量...
100%|█████████████████████████████████████| 5/5 [00:09<00:00,  1.90s/it]

请输入查询(输入 'exit' 退出):
> 一个公司的创建需要具备什么条件

🔍 最相似的段落:
1. 注册公司需要准备身份证、注册地址、公司章程等材料。  (距离:6633.3623)
2. 开公司银行账户需要营业执照和法人身份证。  (距离:8122.5732)
3. 营业执照由工商局颁发,需要填写申请表。  (距离:9337.1758)

请输入查询(输入 'exit' 退出):
> 三里屯怎么走

🔍 最相似的段落:
1. 注册公司需要准备身份证、注册地址、公司章程等材料。  (距离:15391.9512)
2. 税务登记是注册公司的后续步骤。  (距离:15656.2275)
3. 你可以在线申请营业执照。  (距离:16183.6201)

请输入查询(输入 'exit' 退出):
> 注册公司需要准备什么材料

🔍 最相似的段落:
1. 注册公司需要准备身份证、注册地址、公司章程等材料。  (距离:1627.7302)
2. 营业执照由工商局颁发,需要填写申请表。  (距离:5437.8076)
3. 开公司银行账户需要营业执照和法人身份证。  (距离:5667.3779)


main.py(优化版)

import faiss
import os
import numpy as np
from tqdm import tqdm
import dashscope
from dotenv import load_dotenv# 加载 .env 文件中的 API Key
load_dotenv()
dashscope.api_key = os.getenv("DASHSCOPE_API_KEY")# 获取当前脚本所在目录的路径
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
DOC_PATH = os.path.join(BASE_DIR, "documents.txt")# 载入文档
if not os.path.exists(DOC_PATH):raise FileNotFoundError(f"未找到文件:{DOC_PATH}")with open(DOC_PATH, "r", encoding="utf-8") as f:docs = [line.strip() for line in f.readlines() if line.strip()]# 获取阿里百炼的向量
def get_embedding(text):rsp = dashscope.TextEmbedding.call(model="text-embedding-v1",  # 阿里模型名input=text,)return rsp.output["embeddings"][0]["embedding"]# 向量归一化函数
def normalize(vec):norm = np.linalg.norm(vec)return vec / norm if norm > 0 else vec# 生成文档向量
print("🔍 正在生成文档向量...")
doc_embeddings = [normalize(get_embedding(doc)) for doc in tqdm(docs)]# 建立 FAISS 余弦相似度索引(内积模式)
dim = len(doc_embeddings[0])
index = faiss.IndexFlatIP(dim)
index.add(np.array(doc_embeddings).astype("float32"))# 计算欧几里得距离(欧式距离)
def euclidean_distance(vec1, vec2):return float(np.linalg.norm(np.array(vec1) - np.array(vec2)))# 查询函数:使用余弦相似度
def search(query, top_k=3):q_embedding = normalize(get_embedding(query))similarities = []for doc, doc_emb in zip(docs, doc_embeddings):# 计算余弦相似度cosine_sim = float(np.dot(q_embedding, doc_emb))# 计算欧几里得距离dist = euclidean_distance(q_embedding, doc_emb)similarities.append((doc, cosine_sim, dist, doc_emb))# 按余弦相似度排序similarities.sort(key=lambda x: x[1], reverse=True)top_results = similarities[:top_k]print("\n🔍 查询向量:")print(np.round(q_embedding, 4).tolist())print("\n📊 相似文档向量、余弦相似度 & 欧式距离:")for i, (doc, sim, dist, vec) in enumerate(top_results):print(f"\n{i+1}. 文本内容:{doc}")print(f"   文档向量:{np.round(vec, 4).tolist()}")print(f"   余弦相似度:{sim:.4f}")print(f"   欧式距离:{dist:.4f}")return [(doc, sim, dist) for doc, sim, dist, _ in top_results]# 主循环
if __name__ == "__main__":while True:q = input("\n请输入查询(输入 'exit' 退出):\n> ")if q.lower() == "exit":breakresults = search(q)print("\n🔍 最相似的段落(按余弦相似度降序):")for i, (text, sim, dist) in enumerate(results):print(f"{i+1}. {text}  (余弦相似度:{sim:.4f},欧式距离:{dist:.4f})")

运行结果

🔍 正在生成文档向量...
100%|█████████████████████████████████████████████████████████████████████████████████████████████████████| 5/5 [00:12<00:00,  2.59s/it]

请输入查询(输入 'exit' 退出):
> 你好

🔍 查询向量:
[0.0026, -0.0312, 0.0114, 0.0236, -0.0029, 0.0034, 0.0251, -0.0333, -0.0135, 0.0028, -0.0288, 0.0582, 0.0263, -0.0033, 0.0137, -0.0047, -0.0317, 0.016, -0.0047, 0.0211, -0.0313, -0.0203, 0.0066, -0.0228, 0.0292, -0.0183, 0.0028, 0.0084, -0.0164, 0.0071... ]

📊 相似文档向量、余弦相似度 & 欧式距离:

1. 文本内容:你可以在线申请营业执照。
   文档向量:[0.0312, 0.0475, 0.0324, 0.0472, -0.0346, 0.0171, -0.0325, 0.028, -0.0763, -0.0216, -0.0158, 0.0121, -0.0084, -0.0194, 0.0368, -0.0105, 0.0095, -0.0155, 0.0385, 0.013, -0.0147, 0.001, 0.0547, 0.0259, 0.0132, 0.0262, -0.0585, 0.0146, -0.0198, 0.016, ... ]
   余弦相似度:0.1997
   欧式距离:1.2652

2. 文本内容:注册公司需要准备身份证、注册地址、公司章程等材料。
   文档向量:[0.0006, 0.0363, 0.0236, 0.0462, -0.0021, 0.0076, -0.0199, 0.027, -0.0587, -0.0176, -0.0289, -0.0134, 0.0296, -0.0566, 0.0102, -0.006, 0.0052, -0.0242, 0.0255, -0.046, -0.0065, 0.0107, 0.0173, 0.0214, -0.0075, 0.0027, -0.0233, -0.014, -0.0467, 0.0144, ]  

   余弦相似度:0.1473
   欧式距离:1.3059

3. 文本内容:开公司银行账户需要营业执照和法人身份证。
   文档向量:[0.0007, 0.0148, 0.107, 0.009, -0.0025, 0.0103, -0.0273, 0.0553, -0.0794, -0.0432, -0.0285, -0.0105, 0.0291, -0.0292, 0.0212, -0.0296, 0.0196, -0.0294, 0.0092, -0.0325, 0.0117, -0.0071, -0.0013, 0.0267, -0.0065, 0.0112, -0.044, 0.0127, -0.0102...]
   余弦相似度:0.1357
   欧式距离:1.3148

🔍 最相似的段落(按余弦相似度降序):
1. 你可以在线申请营业执照。  (余弦相似度:0.1997,欧式距离:1.2652)
2. 注册公司需要准备身份证、注册地址、公司章程等材料。  (余弦相似度:0.1473,欧式距离:1.3059)
3. 开公司银行账户需要营业执照和法人身份证。  (余弦相似度:0.1357,欧式距离:1.3148)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/diannao/82975.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

matlab中和三角函数相关的内容

和三角相关的函数 以下内容为Ai输出 函数描述示例sin(x)正弦函数&#xff0c;返回x的正弦值&#xff0c;x单位为弧度sin(pi/2)cos(x)余弦函数&#xff0c;返回x的余弦值&#xff0c;x单位为弧度cos(pi)tan(x)正切函数&#xff0c;返回x的正切值&#xff0c;x单位为弧度tan(pi…

scratch基础-外观模块

一、本次任务 二、内容详解 1、模块介绍 1、说[你好] (2)秒&#xff1a;临时对话框&#xff0c;短暂对话 2、说[你好]&#xff1a;持续显示对话框&#xff0c;长文本显示 3、思考[嗯…] (2)秒&#xff1a;临时显示思考气泡&#xff0c;用于角色思考 4、思考[嗯…] &#xff1a…

TAOCMS漏洞代码学习及分析

路由规则 分为前台和后台&#xff0c; 前台在api.php中 <?php session_start(); include(config.php); include(SYS_ROOT.INC.common.php); $ctrl$_REQUEST[ctrl]; $action$_REQUEST[action]; $mucfirst($action); if(!in_array($m,array(Api,Comment)))d…

Spring @Scheduled注解详解

文章目录 1.Scheduled注解定义2.配置 Scheduled2.1 开启定时任务支持2.2 创建定时任务 3. 常用属性3.1 fixedRate3.2 fixedDelay3.3 cron 4.工作原理4.1 基于TaskScheduler4.2 使用 ThreadPoolTaskScheduler4.3 定时任务的执行流程 5. 延时执行的定时任务5.1 创建定时任务类5.2…

理解计算机系统_并发编程(5)_基于线程的并发(二):线程api和基于线程的并发服务器

前言 以<深入理解计算机系统>(以下称“本书”)内容为基础&#xff0c;对程序的整个过程进行梳理。本书内容对整个计算机系统做了系统性导引,每部分内容都是单独的一门课.学习深度根据自己需要来定 引入 接续上一篇理解计算机系统_并发编程(4)_基于线程的并发(一…

使用PhpStudy搭建Web测试服务器

一、安装PhpStudy 从以下目录下载PhpStudy安装文件 Windows版phpstudy下载 - 小皮面板(phpstudy) (xp.cn) 安装成功之后打开如下界面 点击启动Apache 查看网站地址 在浏览器中输入localhost:88,出现如下页面就ok了 二、与Unity交互 1.配置下载文件路径&#xff0c;点击…

cocos creator 3.8 下的 2D 改动

在B站找到的系统性cocos视频教程,纯2D开发入门,链接如下: zzehz黑马程序员6天实战游戏开发微信小程序&#xff08;Cocos2d的升级版 CocosCreator JavaScript&#xff09;_哔哩哔哩_bilibili黑马程序员6天实战游戏开发微信小程序&#xff08;Cocos2d的升级版 CocosCreator Ja…

【Hot 100】208. 实现 Trie (前缀树)

目录 引言实现 Trie (前缀树)我的解题代码解析代码思路分析优化建议1. 内存泄漏问题2. 使用智能指针优化内存管理3. 输入合法性校验&#xff08;可选&#xff09;4. 其他优化 总结 &#x1f64b;‍♂️ 作者&#xff1a;海码007&#x1f4dc; 专栏&#xff1a;算法专栏&#x1…

Unity3D仿星露谷物语开发42之粒子系统

1、目标 使用例子系统&#xff0c;实现割草后草掉落的特效。 通过PoolManager获取特效预制体&#xff0c;通过VFXManager来触发特效。 2、配置例子特效 在Hierarchy -> PersistentScene下创建新物体命名为Reaping。 给该物体添加Particle System组件。 配置例子系统参数…

视觉-语言基础模型作为高效的机器人模仿学习范式

摘要 近期&#xff0c;视觉语言基础模型领域取得的进展彰显了其在理解多模态数据以及解决复杂视觉语言任务&#xff08;包括机器人操作任务&#xff09;方面的能力。我们致力于探寻一种简便的方法&#xff0c;利用现有的视觉语言模型&#xff08;VLMs&#xff09;&#xff0c;仅…

zst-2001 上午题-历年真题 算法(5个内容)

回溯 算法 - 第1题 找合适的位置&#xff0c;如果没有位置就按B回家 d 分治 算法 - 第2题 b 算法 - 第3题 a 算法 - 第4题 划分一般就是分治 a 算法 - 第5题 分治 a 0-1背包 算法 - 第6题 c 算法 - 第7题 最小的为c 3100 c 算法 - 第8题 …

浅论3DGS溅射模型在VR眼镜上的应用

摆烂仙君小课堂开课了&#xff0c;本期将介绍如何手搓VR眼镜&#xff0c;并将随手拍的电影变成3D视频。 一、3DGS模型介绍 3D 高斯模型是基于高斯函数构建的用于描述三维空间中数据分布概率的模型&#xff0c;高斯函数在数学和物理领域有着广泛应用&#xff0c;其在 3D 情境下…

2025年中期大语言模型实力深度剖析

I. 引言&#xff1a;解读2025年动态LLM竞技场中的“实力” 用户提出的“如今哪个大语言模型最强”这一问题&#xff0c;精准地反映了业界对飞速发展的人工智能&#xff08;AI&#xff09;领域的高度关注。本报告基于截至2025年5月的最新数据&#xff0c;旨在对这一问题进行全面…

Spark缓存-cache

一、RDD持久化 1.什么时候该使用持久化&#xff08;缓存&#xff09; 2. RDD cache & persist 缓存 3. RDD CheckPoint 检查点 4. cache & persist & checkpoint 的特点和区别 特点 区别 二、cache & persist 的持久化级别及策略选择 Spark的几种持久化…

嵌入式开发学习日志(数据结构--顺序结构单链表)Day19

一、顺序结构 安装软件命令&#xff1a; sudo apt-get install (软件名) 安装格式化对齐&#xff1a;sudo apt-get install clang-format 内存泄漏检测工具&#xff1a; sudo apt-get install valgrind 编译后&#xff0c;使用命令 valgrind ./a.out 即可看内…

第六节第二部分:抽象类的应用-模板方法设计模式

模板方法设计模式的写法 建议使用final关键字修饰模板方法 总结 代码&#xff1a; People(父类抽象类) package com.Abstract3; public abstract class People {/*设计模板方法设计模式* 1.定义一个模板方法出来*/public final void write(){System.out.println("\t\t\t…

2025年渗透测试面试题总结-渗透测试红队面试三(题目+回答)

网络安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 渗透测试红队面试三 六十一、主机被入侵自查解决方案 六十二、NAT&#xff08;网络地址转换&#xff…

springboot-web基础

21.web spring MVC 基于浏览器的 B/S 结构应用十分流行。Spring Boot 非常适合 Web 应用开发。可以使用嵌入式 Tomcat、Jetty、 Undertow 或 Netty 创建一个自包含的 HTTP 服务器。一个 Spring Boot 的 Web 应用能够自己独立运行&#xff0c;不依赖需 要安装的 Tomcat&#x…

重构Cursor无限电子邮箱注册系统的技术实践

引言 在当今数字化时代&#xff0c;电子邮箱已成为个人和企业网络身份的基础。作为开发者&#xff0c;我们往往会遇到需要设计注册系统的场景&#xff0c;而如何构建一个既安全又用户友好的邮箱注册系统&#xff0c;是值得深入探讨的话题。本文将围绕Cursor邮箱系统的技术重构…

2025.05.10京东机考真题算法岗-第三题

📌 点击直达笔试专栏 👉《大厂笔试突围》 💻 春秋招笔试突围在线OJ 👉 笔试突围OJ 03. 忍者屋顶之旅 问题描述 LYA是一位身手敏捷的忍者,正在一个古老的村庄进行飞檐走壁的训练。村庄有两排房屋,每排从左到右排列着 n n