Commit f73e2a81 f73e2a8106c4f54f3f03632606fcf3d8c9cea24f by 沈秋雨

修正prechunk链接出错

1 parent 89f85cbe
...@@ -21,6 +21,8 @@ RAGAS_GENERATOR_MODEL=gpt-4o-mini ...@@ -21,6 +21,8 @@ RAGAS_GENERATOR_MODEL=gpt-4o-mini
21 RAGAS_JUDGE_MODEL=gpt-4o-mini 21 RAGAS_JUDGE_MODEL=gpt-4o-mini
22 RAGAS_EMBEDDING_MODEL=text-embedding-3-small 22 RAGAS_EMBEDDING_MODEL=text-embedding-3-small
23 RAGAS_ENABLE_THINKING=false 23 RAGAS_ENABLE_THINKING=false
24 RAGAS_HTTP_KEEPALIVE=false
25 RAGAS_TESTSET_TRANSFORMS=single_hop_entities
24 26
25 TESTSET_SIZE=50 27 TESTSET_SIZE=50
26 TESTSET_RAGAS_MODE=direct 28 TESTSET_RAGAS_MODE=direct
......
...@@ -40,6 +40,8 @@ cp .env.example .env ...@@ -40,6 +40,8 @@ cp .env.example .env
40 - `RAGAS_EMBEDDING_BASE_URL` 指向 Infinity embedding 的 OpenAI-compatible `/v1` 40 - `RAGAS_EMBEDDING_BASE_URL` 指向 Infinity embedding 的 OpenAI-compatible `/v1`
41 - `RAGAS_*_MODEL` 是评估侧模型名称 41 - `RAGAS_*_MODEL` 是评估侧模型名称
42 - `RAGAS_ENABLE_THINKING=false` 只会在本评估项目的 RAGAS LLM 请求中发送 `chat_template_kwargs.enable_thinking=false`,不会改变 WeKnora 检索/问答服务的模型配置 42 - `RAGAS_ENABLE_THINKING=false` 只会在本评估项目的 RAGAS LLM 请求中发送 `chat_template_kwargs.enable_thinking=false`,不会改变 WeKnora 检索/问答服务的模型配置
43 - `RAGAS_HTTP_KEEPALIVE=false` 会让 RAGAS LLM 请求使用短连接,规避长流程中 async HTTP 连接清理问题
44 - `RAGAS_TESTSET_TRANSFORMS=single_hop_entities` 会让 `prechunked` 只运行单跳 QA 所需的实体抽取 transform;设为 `default` 可回到 Ragas 默认 prechunked transforms
43 45
44 ## 首轮 Pilot 46 ## 首轮 Pilot
45 47
......
...@@ -297,12 +297,16 @@ TESTSET_RAGAS_MODE=direct ...@@ -297,12 +297,16 @@ TESTSET_RAGAS_MODE=direct
297 TESTSET_GENERATOR_MAX_TOKENS=4096 297 TESTSET_GENERATOR_MAX_TOKENS=4096
298 TESTSET_MAX_DOCUMENT_CHARS=2000 298 TESTSET_MAX_DOCUMENT_CHARS=2000
299 RAGAS_ENABLE_THINKING=false 299 RAGAS_ENABLE_THINKING=false
300 RAGAS_HTTP_KEEPALIVE=false
301 RAGAS_TESTSET_TRANSFORMS=default
300 ``` 302 ```
301 303
302 `direct` 模式会跳过 Ragas 默认的 `HeadlinesExtractor``SummaryExtractor``NERExtractor` 文档预处理链路,直接把 WeKnora chunks 组装成 Ragas KnowledgeGraph 并生成单跳 QA。`prechunked``langchain_docs` 仅用于对比实验,遇到本地 vLLM 结构化输出不稳定时不建议使用。 304 `direct` 模式会跳过 Ragas 默认的 `HeadlinesExtractor``SummaryExtractor``NERExtractor` 文档预处理链路,直接把 WeKnora chunks 组装成 Ragas KnowledgeGraph 并生成单跳 QA。`prechunked``langchain_docs` 仅用于对比实验,遇到本地 vLLM 结构化输出不稳定时不建议使用。
303 305
304 如果使用 Qwen thinking 模型,`RAGAS_ENABLE_THINKING=false` 会只在 RAGAS 请求里附加 `chat_template_kwargs.enable_thinking=false`,避免 RAGAS 的 JSON/Pydantic 结构化输出被 `Thinking Process` 前缀破坏;WeKnora 本身的检索问答链路不经过这些脚本,不会受影响。 306 如果使用 Qwen thinking 模型,`RAGAS_ENABLE_THINKING=false` 会只在 RAGAS 请求里附加 `chat_template_kwargs.enable_thinking=false`,避免 RAGAS 的 JSON/Pydantic 结构化输出被 `Thinking Process` 前缀破坏;WeKnora 本身的检索问答链路不经过这些脚本,不会受影响。
305 307
308 如果 `prechunked` 模式在本地 vLLM 上出现 `Event loop is closed``APIConnectionError`,保持 `RAGAS_HTTP_KEEPALIVE=false`。如果想验证 Ragas 默认 prechunked transforms,可临时设置 `RAGAS_TESTSET_TRANSFORMS=default`,但它会重新启用 summary/filter/theme/relationship 等更重的中间步骤。
309
306 如果 vLLM 仍然报生成未完成,先把 `TESTSET_SIZE` 降到 3,再把 `TESTSET_MAX_DOCUMENT_CHARS` 调到 1000-1500 验证链路;`ragas.max_tokens` 主要用于后续评测阶段,不应该拿来无限放大测试集生成阶段的输出长度。 310 如果 vLLM 仍然报生成未完成,先把 `TESTSET_SIZE` 降到 3,再把 `TESTSET_MAX_DOCUMENT_CHARS` 调到 1000-1500 验证链路;`ragas.max_tokens` 主要用于后续评测阶段,不应该拿来无限放大测试集生成阶段的输出长度。
307 311
308 ### WeKnora 问答没有 retrieved_contexts 312 ### WeKnora 问答没有 retrieved_contexts
......
...@@ -73,6 +73,8 @@ ragas: ...@@ -73,6 +73,8 @@ ragas:
73 judge_model: "${RAGAS_JUDGE_MODEL}" 73 judge_model: "${RAGAS_JUDGE_MODEL}"
74 embedding_model: "${RAGAS_EMBEDDING_MODEL}" 74 embedding_model: "${RAGAS_EMBEDDING_MODEL}"
75 enable_thinking: "${RAGAS_ENABLE_THINKING:-false}" 75 enable_thinking: "${RAGAS_ENABLE_THINKING:-false}"
76 http_keepalive: "${RAGAS_HTTP_KEEPALIVE:-false}"
77 testset_transforms: "${RAGAS_TESTSET_TRANSFORMS:-single_hop_entities}"
76 temperature: 0 78 temperature: 0
77 max_tokens: 4096 79 max_tokens: 4096
78 timeout_seconds: 600 80 timeout_seconds: 600
......
...@@ -10,8 +10,21 @@ def chat_extra_body(config: dict[str, Any]) -> dict[str, Any]: ...@@ -10,8 +10,21 @@ def chat_extra_body(config: dict[str, Any]) -> dict[str, Any]:
10 10
11 11
12 def chat_openai_kwargs(config: dict[str, Any]) -> dict[str, Any]: 12 def chat_openai_kwargs(config: dict[str, Any]) -> dict[str, Any]:
13 kwargs: dict[str, Any] = {}
13 extra_body = chat_extra_body(config) 14 extra_body = chat_extra_body(config)
14 return {"extra_body": extra_body} if extra_body else {} 15 if extra_body:
16 kwargs["extra_body"] = extra_body
17 if not _as_bool(config.get("http_keepalive", False)):
18 try:
19 import httpx
20 except ImportError:
21 return kwargs
22 timeout_seconds = float(config.get("timeout_seconds", 600))
23 limits = httpx.Limits(max_connections=1, max_keepalive_connections=0)
24 timeout = httpx.Timeout(timeout_seconds)
25 kwargs["http_client"] = httpx.Client(limits=limits, timeout=timeout)
26 kwargs["http_async_client"] = httpx.AsyncClient(limits=limits, timeout=timeout)
27 return kwargs
15 28
16 29
17 def _as_bool(value: Any) -> bool: 30 def _as_bool(value: Any) -> bool:
......
...@@ -20,6 +20,7 @@ from ragas.testset.synthesizers.single_hop.base import ( ...@@ -20,6 +20,7 @@ from ragas.testset.synthesizers.single_hop.base import (
20 from ragas.testset.synthesizers.single_hop.specific import ( 20 from ragas.testset.synthesizers.single_hop.specific import (
21 SingleHopSpecificQuerySynthesizer, 21 SingleHopSpecificQuerySynthesizer,
22 ) 22 )
23 from ragas.testset.transforms.extractors.llm_based import NERExtractor
23 24
24 from weknora_eval.config import require_config 25 from weknora_eval.config import require_config
25 from weknora_eval.loaders import read_jsonl, write_jsonl 26 from weknora_eval.loaders import read_jsonl, write_jsonl
...@@ -238,6 +239,7 @@ def _generate_ragas_prechunked( ...@@ -238,6 +239,7 @@ def _generate_ragas_prechunked(
238 return generator.generate_with_chunks( 239 return generator.generate_with_chunks(
239 documents, 240 documents,
240 testset_size=size, 241 testset_size=size,
242 transforms=_prechunked_transforms(ragas_config, ragas_llm),
241 query_distribution=[(SingleHopSpecificQuerySynthesizer(llm=ragas_llm), 1.0)], 243 query_distribution=[(SingleHopSpecificQuerySynthesizer(llm=ragas_llm), 1.0)],
242 run_config=run_config, 244 run_config=run_config,
243 raise_exceptions=True, 245 raise_exceptions=True,
...@@ -264,6 +266,19 @@ def _generate_ragas_langchain_docs( ...@@ -264,6 +266,19 @@ def _generate_ragas_langchain_docs(
264 return generator.generate_with_langchain_docs(documents, **generate_kwargs) 266 return generator.generate_with_langchain_docs(documents, **generate_kwargs)
265 267
266 268
269 def _prechunked_transforms(ragas_config: dict[str, Any], ragas_llm: Any) -> Any:
270 mode = str(ragas_config.get("testset_transforms", "single_hop_entities"))
271 if mode == "default":
272 return None
273 if mode == "single_hop_entities":
274 return [NERExtractor(llm=ragas_llm, filter_nodes=_is_chunk_node)]
275 raise ValueError(f"Unsupported ragas.testset_transforms: {mode}")
276
277
278 def _is_chunk_node(node: Any) -> bool:
279 return getattr(getattr(node, "type", None), "name", "") == "CHUNK"
280
281
267 def _build_embeddings( 282 def _build_embeddings(
268 config: dict[str, Any], ragas_config: dict[str, Any] 283 config: dict[str, Any], ragas_config: dict[str, Any]
269 ) -> OpenAIEmbeddings: 284 ) -> OpenAIEmbeddings:
......