
在这个过程中很高兴能了解到很多之前没涉猎过的行业和场景,其中经常被集中问到的问题大概有四个:中小企业做RAG知识库落地选择框架哪个比较好?如果选择 RAGFlow 如何进行定制化开发?如何对文档中的图片进行识别检索?如何对复杂文档进行动态分块等。

关于选择什么框架的问题,仁者见仁,需要综合对比的盆友可以参考我之前发的那篇文章企业RAG落地避坑指南:自主开发 vs 三大框架,核心配置与选型全解析。这篇以 RAGFlow 框架为例,针对上述后三个问题结合目前团队实践经验,给各位做个分享,大家辨证参考。
毕竟,RAG并没有“一招鲜”的神奇魔法,传说那几个大厂手里掌握的RAG”核心技术“,私以为也是经过了必要且复杂的“策略优化-管道设计-训练-调优-发布”等专业开发流程,不过成熟的开源应用框架,无疑是更有想象空间的社会化大创新。
注:本篇会比较偏开发导向,非技术向盆友选择性翻翻就好。
以下,enjoy:
1、优化实施路线图
以上篇介绍的机械加工行业的维保场景为例RAGFlow+DeepSeek-R1:14b落地案例分享(足够详细):机加工行业设备维保场景,推荐先采用官方的 Python API 进行合理的优化配置后,再修改项目源码,最后根据业务目标做必要的高级优化拓展。此处附上一张个人项目实施过程中积累的些优化要点,供各位参考:

1.1 阶段一:API 优化配置
配置不同文档类型的解析策略
调整检索参数优化语义搜索质量
定制大模型提示词以适应机械行业特点
1.2 阶段二:基础源码修改
实现专业术语处理模块
开发查询路由机制
增加上下文增强功能
1.3 阶段三:高级优化扩展
实现多级索引结构
开发高性能缓存机制
添加查询日志分析系统
2、6 个官方 Python API 优化全解析
根据 RAGFlow 官方 Python API 文档,为大家完整梳理了所有可进行 API 优化的模块和参数。这些 API 调优可以不修改源码,直接通过参数配置实现性能提升。
建议在看完之后还是去官网看下原文,亲自动手试过一遍会有不一样的体感。原文出处:

2.1 数据集管理
创建数据集 create_dataset
优化参数:
- embedding_model: 选择合适的嵌入模型,影响检索质量
中文场景推荐: "BAAI/bge-large-zh-v1.5"
英文场景可选: "BAAI/bge-large-en-v1.5"
- language: 选择与文档匹配的语言
- chunk_method: 关键参数,根据文档类型选择最佳分块策略
"naive": 通用文档
"paper": 论文/设备手册
"book": 结构化书籍
"table": 表格数据
"qa": 问答格式文档
"picture": 图片文档
"one": 整个文档作为一个块
"knowledge_graph": 知识图谱
chunk_token_num: 控制分块大小
delimiter: 自定义分隔符
layout_recognize: 是否启用布局识别
raptor: 高级解析选项
更新数据集 DataSet.update
优化参数:
embedding_model: 更换更适合的嵌入模型
chunk_method: 调整分块策略
meta_fields: 更新元数据字段
2.2 文件管理 (FILE MANAGEMENT)
上传文档 DataSet.upload_documents
优化参数:
display_name: 文件显示名,方便检索与管理
blob: 文件内容
更新文档 Document.update
优化参数:
- chunk_method: 文档分块方法
- parser_config: 文档解析配置
对于图文文档,可设置: "layout_recognize": True
对于表格文档,可设置: "html4excel": True
解析文档
用于触发文档解析流程,支持批量处理。
2.3 分块管理 (CHUNK MANAGEMENT)
添加分块 Document.add_chunk
优化参数:
important_keywords: 关键词标注,增强检索相关性
更新分块 Chunk.update
优化参数:
content: 更新分块内容
important_keywords: 更新关键词
available: 控制分块可用性
检索 RAGFlow.retrieve(关键API)
优化参数 (最重要的检索相关参数):
- similarity_threshold: 相似度阈值,影响召回范围
- vector_similarity_weight: 向量相似度权重与关键词匹配权重的比例
设置为 0-1 之间,值越大向量权重越高
工业领域建议参考0.3-0.5,平衡专业术语与语义理解
- top_k: 参与向量检索的 chunk 数量,影响检索范围
- rerank_id: 重排序模型 ID,提升检索精度
- keyword: 开启关键词匹配,对专业领域极其有用
- highlight: 高亮匹配内容,帮助理解匹配原因
2.4 聊天助手管理
创建聊天助手 RAGFlow.create_chat
优化参数:
model_name: 模型名称
temperature: 温度,影响创造性
top_p: 词汇采样范围
presence_penalty: 重复惩罚
frequency_penalty: 频率惩罚
max_token: 最大输出 token 数
similarity_threshold: 相似度阈值
keywords_similarity_weight: 关键词相似度权重
top_n: 提供给 LLM 的 chunk 数量
rerank_model: 重排序模型
top_k: 重排序参与的候选数量 empty_response: 无匹配时的回复
show_quote: 是否显示引用来源
prompt: 系统提示词内容
更新聊天助手 Chat.update
优化参数: 同 create_chat 中的参数
2.5 会话管理 (SESSION MANAGEMENT)
创建会话 Chat.create_session
提问 Session.ask
优化参数:
stream: 流式输出,提升用户体验
**kwargs: 可传递给 prompt 中定义的变量
2.6 代理管理 (AGENT MANAGEMENT)
创建代理会话 Agent.create_session
代理提问 Session.ask
与普通会话的ask方法类似。
3、调整项目源码思路参考
3.1 专业术语处理
需要在检索引擎层面添加工业领域同义词和术语映射:
修改点:
在查询预处理阶段添加定制的术语处理模块
需要在 RAGFlow 的查询管道中修改源码添加此功能
3.2 多级索引结构实现
需要定制 Milvus 索引策略,实现基础索引层和语义索引层的混合索引:
修改点:
修改 RAGFlow 的索引构建模块扩展
Milvus 客户端接口以支持多索引策略
3.3 查询路由设计
需要实现定制化的查询路由逻辑,识别不同类型的查询并路由到最合适的检索通道:
修改点:
在 RAGFlow 的查询处理流程中添加查询分类和路由机制
实现针对不同查询类型的专用处理通道
3.4 上下文增强机制
增加查询上下文增强,融入设备信息、历史记录等:
修改点:
修改会话管理模块,实现会话状态跟踪
增加设备元数据关联机制
在查询处理流程中加入上下文增强步骤
4、图文结合文档处理方案
依然是两种方案,直接使用RAGFlow API方案优势是更简单,使用现有功能,无需额外的模型调用,也能够直接显示原始图片,视觉效果更好,处理速度更快,不依赖外部 API,当然成本也无疑更低。
但使用一个多模态模型进行预处理的方案优势也很明显,图片内容被转换为文本,便于向量化和语义搜索,也可以依托多模态模型的能力,提供更丰富的图片内容解释。

目前实际测试下来,采用两种方案的组合,效果更加稳定。
4.1 使用多模态预处理生成图片描述
4.2 使用 RAGFlow 处理和存储原始图片
4.3 创建能够提供文本描述和图片引用的助手
4.4 源码修改的一些建议
增强图片提取和处理:
修改 PDF 解析器,更准确地绑定文本和相关图片
增加图片内容分析功能,自动标注图片类型(如"故障图"、"结构图"等)
实现图文混合索引:
为图片创建特殊索引,支持通过图片内容或相关文本检索图片
在检索结果中包含图片 URL 或直接嵌入图片
改进响应生成:
修改聊天助手的响应生成逻辑,自动识别图片引用
在生成的回答中包含相关图片或图片链接
5、动态分块策略参考
RAGFlow的chunk_method参数是在数据集级别或文档级别设置的,不支持在单个文档内部动态切换不同的分块策略。但实际情况是,同一文档中的不同部分可能需要不同的处理方式,比如针对段落、图片、表格、图表等,使用单一的分块策略很难同时兼顾所有这些内容类型的特点。
5.1 4种分块策略对比
源码修改方案:
修改 RAGFlow 的文档解析器,使其能够识别文档中的不同部分并应用不同的分块策略,但这需要深入修改 RAGFlow 的核心处理逻辑,如果没有深入理解RAGFlow的全局代码,建议不要这么做。
文档预处理方案:
在上传到 RAGFlow 前预处理文档,将其拆分成不同类型的子文档。例如,将设备手册拆分为纯文本部分、表格部分、图文部分等然后分别上传到不同的数据集,每个数据集使用适合的分块策略。
这个方案优点是,可以充分利用RAGFlow针对不同内容类型的专门分块策略,但问题也很明显,就是文档上下文被拆分,可能影响整体理解。
自定义分块方案:
不使用RAGFlow 的自动分块,而是手动控制分块,使用chunk_method="one"将整个文档作为一个块导入,然后使用自定义逻辑创建更细粒度的分块。这种做法无疑可以实现最精细的控制、保留文档完整性,当然缺点就是实现上会相对麻烦。
混合模型方案:
创建多个使用不同分块策略的数据集,将同一文档上传到所有这些数据集,在检索时查询所有数据集并合并结果。这种方法保持文档完整性,但创建多个使用不同分块策略的副本,会造成存储冗余,检索时需要合并多个结果集。
5.2 推荐自定义方案
这种方法使用RAGFlow的API但完全控制分块过程,最灵活且无需修改源码。

完整保留原始文档:
使用 chunk_method="one"将文档整体上传保留文档的完整性和上下文关系
自定义内容识别:
使用 PyMuPDF 识别文档中的不同内容类型:
文本、段落、表格内容图片及其相关描述、章节标题和结构
动态创建精细分块:
文本块: 基于段落和语义分界
表格块: 保留表格结构和行列关系
图文块: 关联图片和周围的描述文本
添加分块类型标记:
每个分块添加类型标识符[text], [table], [image]等
方便检索时区分不同类型的内容
丰富关键词提取:
为每个分块提取相关关键词
保留章节上下文信息
from ragflow_sdk import RAGFlow
import fitz # PyMuPDF
import re
import pandas as pd
import io
import logging
from typing import List, Dict, Any, Tuple
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
class DynamicChunker:
"""针对混合格式文档的自定义分块器"""
def __init__(self, api_key: str, base_url: str):
self.rag_object = RAGFlow(api_key=api_key, base_url=base_url)
def process_document(self, pdf_path: str, dataset_name: str = None) -> str:
"""处理PDF文档并实现自定义分块"""
# 1. 创建或获取数据集
if dataset_name:
datasets = self.rag_object.list_datasets(name=dataset_name)
if datasets:
dataset = datasets[0]
logger.info(f"使用现有数据集: {dataset.name}, ID: {dataset.id}")
else:
dataset = self.rag_object.create_dataset(
name=dataset_name,
embedding_model="BAAI/bge-large-zh-v1.5",
language="Chinese",
chunk_method="one" # 使用"one"方式,保持文档完整性
)
logger.info(f"创建新数据集: {dataset.name}, ID: {dataset.id}")
else:
dataset = self.rag_object.create_dataset(
name="混合文档库",
embedding_model="BAAI/bge-large-zh-v1.5",
language="Chinese",
chunk_method="one"
)
logger.info(f"创建新数据集: {dataset.name}, ID: {dataset.id}")
# 2. 上传文档
with open(pdf_path, "rb") as f:
document_blob = f.read()
docs = dataset.upload_documents([{
"display_name": pdf_path.split("/")[-1],
"blob": document_blob
}])
if not docs:
logger.error("文档上传失败")
return None
doc = docs[0]
logger.info(f"文档上传成功, ID: {doc.id}")
# 3. 分析文档结构并创建自定义分块
chunks = self._create_custom_chunks(pdf_path)
logger.info(f"创建了 {len(chunks)} 个自定义分块")
# 4. 手动添加分块到文档
chunk_ids = []
for chunk in chunks:
content = chunk["content"]
keywords = chunk["keywords"]
chunk_type = chunk["type"]
# 添加分块类型标记以便未来检索
content_with_marker = f"[{chunk_type}]\n{content}"
# 添加分块
new_chunk = doc.add_chunk(
cnotallow=content_with_marker,
important_keywords=keywords
)
chunk_ids.append(new_chunk.id)
logger.info(f"添加分块: 类型={chunk_type}, ID={new_chunk.id}, 关键词数量={len(keywords)}")
return doc.id
def _create_custom_chunks(self, pdf_path: str) -> List[Dict[str, Any]]:
"""分析PDF并创建自定义分块"""
pdf_doc = fitz.open(pdf_path)
chunks = []
# 用于存储当前上下文
current_section = ""
current_text_chunk = ""
current_table_data = []
current_keywords = []
for page_idx, page in enumerate(pdf_doc):
# 提取页面文本
text = page.get_text()
# 检测章节标题
section_headers = self._detect_section_headers(text)
if section_headers:
# 如果有积累的文本块,先保存
if current_text_chunk:
chunks.append({
"content": current_text_chunk,
"keywords": list(set(current_keywords)),
"type": "text",
"section": current_section
})
current_text_chunk = ""
current_keywords = []
# 更新当前章节
current_section = section_headers[0]
current_keywords.append(current_section)
# 检测表格
tables = self._detect_tables(page)
if tables:
# 如果有积累的文本块,先保存
if current_text_chunk:
chunks.append({
"content": current_text_chunk,
"keywords": list(set(current_keywords)),
"type": "text",
"section": current_section
})
current_text_chunk = ""
current_keywords = []
# 处理表格
for table in tables:
table_content = self._format_table(table)
table_keywords = self._extract_keywords_from_table(table)
chunks.append({
"content": table_content,
"keywords": list(set(table_keywords + current_keywords)),
"type": "table",
"section": current_section
})
# 检测图片
images = self._detect_images(page)
for img_idx, img in enumerate(images):
# 提取图片周围的文本作为上下文
img_context = self._extract_image_context(text, img["bbox"])
# 如果找到图片相关文本
if img_context:
# 如果有积累的文本块,先保存
if current_text_chunk:
chunks.append({
"content": current_text_chunk,
"keywords": list(set(current_keywords)),
"type": "text",
"section": current_section
})
current_text_chunk = ""
current_keywords = []
# 创建图文块
image_text_content = f"图片描述: {img_context}\n图片位置: 第{page_idx+1}页"
image_keywords = self._extract_keywords(img_context)
chunks.append({
"content": image_text_content,
"keywords": list(set(image_keywords + current_keywords)),
"type": "image",
"section": current_section
})
# 防止重复处理同一段文本
text = text.replace(img_context, "", 1)
# 处理剩余文本
if text.strip():
# 按段落拆分
paragraphs = self._split_into_paragraphs(text)
for para in paragraphs:
if len(para.strip()) < 10: # 忽略太短的段落
continue
# 累积文本直到达到合适的大小
current_text_chunk += para + "\n\n"
current_keywords.extend(self._extract_keywords(para))
# 检查是否应该创建新的文本块
if len(current_text_chunk) > 1500: # 大约300-500个词
chunks.append({
"content": current_text_chunk,
"keywords": list(set(current_keywords)),
"type": "text",
"section": current_section
})
current_text_chunk = ""
current_keywords = []
# 处理最后一个文本块
if current_text_chunk:
chunks.append({
"content": current_text_chunk,
"keywords": list(set(current_keywords)),
"type": "text",
"section": current_section
})
return chunks
def _detect_section_headers(self, text: str) -> List[str]:
"""检测章节标题"""
# 这是一个简化的实现,可以根据实际文档格式调整
header_patterns = [
r"^第[一二三四五六七八九十\d]+章\s*(.+)$",
r"^\d+\.\d*\s+(.+)$",
r"^[一二三四五六七八九十]+[、..]\s*(.+)$"
]
headers = []
for line in text.split("\n"):
line = line.strip()
for pattern in header_patterns:
match = re.match(pattern, line)
if match:
headers.append(line)
break
return headers
def _detect_tables(self, page) -> List[Any]:
"""检测页面中的表格"""
# 这里使用简化的检测逻辑,实际应用中可能需要更复杂的表格检测算法
# 例如,可以寻找包含多个垂直和水平线的区域
tables = []
# 简单表格检测:查找水平线和垂直线的集中区域
# 这里仅作为占位示例,实际实现会更复杂
horizontal_lines = []
vertical_lines = []
for drawing in page.get_drawings():
for item in drawing["items"]:
if item["type"] == "l": # 线段
x0, y0, x1, y1 = item["rect"]
if abs(y1 - y0) < 2: # 水平线
horizontal_lines.append((x0, y0, x1, y1))
elif abs(x1 - x0) < 2: # 垂直线
vertical_lines.append((x0, y0, x1, y1))
# 简单的表格判定:有足够多的水平线和垂直线
if len(horizontal_lines) >= 3 and len(vertical_lines) >= 2:
# 找出所有线的边界,作为表格边界
min_x = min([min(l[0], l[2]) for l in horizontal_lines + vertical_lines])
max_x = max([max(l[0], l[2]) for l in horizontal_lines + vertical_lines])
min_y = min([min(l[1], l[3]) for l in horizontal_lines + vertical_lines])
max_y = max([max(l[1], l[3]) for l in horizontal_lines + vertical_lines])
# 提取表格区域的文本
table_rect = fitz.Rect(min_x, min_y, max_x, max_y)
table_text = page.get_text("text", clip=table_rect)
# 简化的表格结构化(实际应用中需要更复杂的逻辑)
table_rows = table_text.split("\n")
table = []
for row in table_rows:
if row.strip():
cells = row.split()
if len(cells) >= 2: # 至少有2个单元格才视为有效行
table.append(cells)
if table:
tables.append(table)
return tables
def _detect_images(self, page) -> List[Dict[str, Any]]:
"""检测页面中的图片"""
images = []
# 获取页面上的图片对象
img_list = page.get_images(full=True)
for img_idx, img_info in enumerate(img_list):
xref = img_info[0]
base_image = page.parent.extract_image(xref)
if base_image:
# 寻找图片在页面上的位置
img_rects = []
for rect in page.get_image_rects(xref):
img_rects.append(rect)
if img_rects:
# 使用第一个找到的位置
bbox = img_rects[0]
images.append({
"bbox": [bbox.x0, bbox.y0, bbox.x1, bbox.y1]
})
return images
def _extract_image_context(self, text: str, bbox: List[float], context_size: int = 200) -> str:
"""提取图片周围的文本作为上下文"""
# 在文本中查找可能的图片标题,如"图1","Figure 1"等
caption_patterns = [
r"图\s*\d+[\..:]?\s*(.+?)(?:\n|$)",
r"Figure\s*\d+[\.:]?\s*(.+?)(?:\n|$)",
r"图表\s*\d+[\..:]?\s*(.+?)(?:\n|$)"
]
for pattern in caption_patterns:
matches = re.finditer(pattern, text, re.IGNORECASE)
for match in matches:
return match.group(0)
# 如果找不到明确的图片标题,则尝试提取图片周围的文本
# 这是一个简化实现,实际应用中可能需要更复杂的逻辑
lines = text.split("\n")
total_length = 0
start_line = 0
# 估计图片在文本中的位置
# 这是一个非常粗略的估计,实际应用中需要更精确的方法
relative_position = bbox[1] / 1000 # 假设页面高度为1000
target_position = int(len(text) * relative_position)
# 找到大致对应的行
for i, line in enumerate(lines):
total_length += len(line) + 1 # +1 for newline
if total_length > target_position:
start_line = max(0, i - 2) # 从前两行开始
break
# 提取上下文(当前行及其前后几行)
context_lines = lines[max(0, start_line):min(len(lines), start_line + 5)]
return "\n".join(line for line in context_lines if len(line.strip()) > 5)
def _format_table(self, table: List[List[str]]) -> str:
"""格式化表格为文本格式"""
if not table:
return ""
# 创建pandas DataFrame
df = pd.DataFrame(table[1:], columns=table[0] if len(table) > 1 else None)
# 转换为字符串形式
result = io.StringIO()
df.to_csv(result, sep="|", index=False)
return result.getvalue()
def _extract_keywords_from_table(self, table: List[List[str]]) -> List[str]:
"""从表格中提取关键词"""
keywords = []
# 表头作为关键词
if table and len(table) > 0:
keywords.extend(table[0])
# 第一列可能是行标题,也加入关键词
for row in table[1:] if len(table) > 1 else []:
if row and len(row) > 0:
keywords.append(row[0])
return keywords
def _split_into_paragraphs(self, text: str) -> List[str]:
"""将文本拆分为段落"""
# 按照多个换行符拆分
paragraphs = re.split(r"\n\s*\n", text)
return [p.strip() for p in paragraphs if p.strip()]
def _extract_keywords(self, text: str) -> List[str]:
"""从文本中提取关键词"""
# 这是一个简化的关键词提取方法
# 实际应用中可以使用更复杂的NLP技术,如TF-IDF、TextRank等
# 1. 移除停用词和标点
stop_words = {"的", "了", "和", "与", "或", "在", "是", "有", "被", "将", "把"}
cleaned_text = re.sub(r'[^\w\s]', ' ', text)
words = cleaned_text.split()
filtered_words = [w for w in words if w not in stop_words and len(w) > 1]
# 2. 简单词频统计
word_count = {}
for word in filtered_words:
if word in word_count:
word_count[word] += 1
else:
word_count[word] = 1
# 3. 选择频率最高的几个词作为关键词
sorted_words = sorted(word_count.items(), key=lambda x: x[1], reverse=True)
return [word for word, count in sorted_words[:10] if count > 1]
# 使用示例
if __name__ == "__main__":
chunker = DynamicChunker(
api_key="YOUR_API_KEY",
base_url="http://YOUR_BASE_URL:9380"
)
doc_id = chunker.process_document("设备维修手册.pdf", "动态分块测试")
print(f"处理完成,文档ID: {doc_id}")
- 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.
- 89.
- 90.
- 91.
- 92.
- 93.
- 94.
- 95.
- 96.
- 97.
- 98.
- 99.
- 100.
- 101.
- 102.
- 103.
- 104.
- 105.
- 106.
- 107.
- 108.
- 109.
- 110.
- 111.
- 112.
- 113.
- 114.
- 115.
- 116.
- 117.
- 118.
- 119.
- 120.
- 121.
- 122.
- 123.
- 124.
- 125.
- 126.
- 127.
- 128.
- 129.
- 130.
- 131.
- 132.
- 133.
- 134.
- 135.
- 136.
- 137.
- 138.
- 139.
- 140.
- 141.
- 142.
- 143.
- 144.
- 145.
- 146.
- 147.
- 148.
- 149.
- 150.
- 151.
- 152.
- 153.
- 154.
- 155.
- 156.
- 157.
- 158.
- 159.
- 160.
- 161.
- 162.
- 163.
- 164.
- 165.
- 166.
- 167.
- 168.
- 169.
- 170.
- 171.
- 172.
- 173.
- 174.
- 175.
- 176.
- 177.
- 178.
- 179.
- 180.
- 181.
- 182.
- 183.
- 184.
- 185.
- 186.
- 187.
- 188.
- 189.
- 190.
- 191.
- 192.
- 193.
- 194.
- 195.
- 196.
- 197.
- 198.
- 199.
- 200.
- 201.
- 202.
- 203.
- 204.
- 205.
- 206.
- 207.
- 208.
- 209.
- 210.
- 211.
- 212.
- 213.
- 214.
- 215.
- 216.
- 217.
- 218.
- 219.
- 220.
- 221.
- 222.
- 223.
- 224.
- 225.
- 226.
- 227.
- 228.
- 229.
- 230.
- 231.
- 232.
- 233.
- 234.
- 235.
- 236.
- 237.
- 238.
- 239.
- 240.
- 241.
- 242.
- 243.
- 244.
- 245.
- 246.
- 247.
- 248.
- 249.
- 250.
- 251.
- 252.
- 253.
- 254.
- 255.
- 256.
- 257.
- 258.
- 259.
- 260.
- 261.
- 262.
- 263.
- 264.
- 265.
- 266.
- 267.
- 268.
- 269.
- 270.
- 271.
- 272.
- 273.
- 274.
- 275.
- 276.
- 277.
- 278.
- 279.
- 280.
- 281.
- 282.
- 283.
- 284.
- 285.
- 286.
- 287.
- 288.
- 289.
- 290.
- 291.
- 292.
- 293.
- 294.
- 295.
- 296.
- 297.
- 298.
- 299.
- 300.
- 301.
- 302.
- 303.
- 304.
- 305.
- 306.
- 307.
- 308.
- 309.
- 310.
- 311.
- 312.
- 313.
- 314.
- 315.
- 316.
- 317.
- 318.
- 319.
- 320.
- 321.
- 322.
- 323.
- 324.
- 325.
- 326.
- 327.
- 328.
- 329.
- 330.
- 331.
- 332.
- 333.
- 334.
- 335.
- 336.
- 337.
- 338.
- 339.
- 340.
- 341.
- 342.
- 343.
- 344.
- 345.
- 346.
- 347.
- 348.
- 349.
- 350.
- 351.
- 352.
- 353.
- 354.
- 355.
- 356.
- 357.
- 358.
- 359.
- 360.
- 361.
- 362.
- 363.
- 364.
- 365.
- 366.
- 367.
- 368.
- 369.
- 370.
- 371.
- 372.
- 373.
- 374.
- 375.
- 376.
- 377.
- 378.
- 379.
- 380.
- 381.
- 382.
- 383.
- 384.
- 385.
- 386.
- 387.
- 388.
- 389.
- 390.
- 391.
- 392.
- 393.
- 394.
- 395.
- 396.
- 397.
- 398.
- 399.
- 400.
- 401.
- 402.
- 403.
- 404.
- 405.
- 406.
- 407.
- 408.
- 409.
- 410.
- 411.
- 412.
- 413.
- 414.
- 415.
- 416.
- 417.
- 418.
- 419.
- 420.
- 421.
- 422.
- 423.
- 424.
- 425.
- 426.
- 427.
- 428.
- 429.
- 430.
- 431.
- 432.
- 433.
- 434.
- 435.
- 436.
- 437.
- 438.
- 439.
- 440.
- 441.
- 442.
- 443.
- 444.
- 445.
- 446.
- 447.
- 448.
- 449.
- 450.
- 451.
- 452.
- 453.
- 454.
- 455.
- 456.
- 457.
- 458.
- 459.
- 460.
- 461.
- 462.
- 463.
- 464.
- 465.
- 466.
- 467.
- 468.
- 469.
- 470.
- 471.
- 472.
- 473.
- 474.
- 475.
- 476.
(完)