Feat: add citation option to agent and enlarge the timeouts. (#9484)

### What problem does this PR solve?

#9422

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
Kevin Hu
2025-08-15 10:05:01 +08:00
committed by GitHub
parent 562349eb02
commit 2114e966d8
6 changed files with 22 additions and 21 deletions

View File

@ -244,7 +244,7 @@ class Agent(LLM, ToolBase):
def complete(): def complete():
nonlocal hist nonlocal hist
need2cite = self._canvas.get_reference()["chunks"] and self._id.find("-->") < 0 need2cite = self._param.cite and self._canvas.get_reference()["chunks"] and self._id.find("-->") < 0
cited = False cited = False
if hist[0]["role"] == "system" and need2cite: if hist[0]["role"] == "system" and need2cite:
if len(hist) < 7: if len(hist) < 7:

View File

@ -145,7 +145,7 @@ class LLM(ComponentBase):
prompt = self.string_format(prompt, args) prompt = self.string_format(prompt, args)
for m in msg: for m in msg:
m["content"] = self.string_format(m["content"], args) m["content"] = self.string_format(m["content"], args)
if self._canvas.get_reference()["chunks"]: if self._param.cite and self._canvas.get_reference()["chunks"]:
prompt += citation_prompt() prompt += citation_prompt()
return prompt, msg return prompt, msg

View File

@ -106,7 +106,7 @@ class EntityResolution(Extractor):
nonlocal remain_candidates_to_resolve, callback nonlocal remain_candidates_to_resolve, callback
async with semaphore: async with semaphore:
try: try:
with trio.move_on_after(180) as cancel_scope: with trio.move_on_after(280) as cancel_scope:
await self._resolve_candidate(candidate_batch, result_set, result_lock) await self._resolve_candidate(candidate_batch, result_set, result_lock)
remain_candidates_to_resolve = remain_candidates_to_resolve - len(candidate_batch[1]) remain_candidates_to_resolve = remain_candidates_to_resolve - len(candidate_batch[1])
callback(msg=f"Resolved {len(candidate_batch[1])} pairs, {remain_candidates_to_resolve} are remained to resolve. ") callback(msg=f"Resolved {len(candidate_batch[1])} pairs, {remain_candidates_to_resolve} are remained to resolve. ")
@ -169,7 +169,7 @@ class EntityResolution(Extractor):
logging.info(f"Created resolution prompt {len(text)} bytes for {len(candidate_resolution_i[1])} entity pairs of type {candidate_resolution_i[0]}") logging.info(f"Created resolution prompt {len(text)} bytes for {len(candidate_resolution_i[1])} entity pairs of type {candidate_resolution_i[0]}")
async with chat_limiter: async with chat_limiter:
try: try:
with trio.move_on_after(120) as cancel_scope: with trio.move_on_after(240) as cancel_scope:
response = await trio.to_thread.run_sync(self._chat, text, [{"role": "user", "content": "Output:"}], {}) response = await trio.to_thread.run_sync(self._chat, text, [{"role": "user", "content": "Output:"}], {})
if cancel_scope.cancelled_caught: if cancel_scope.cancelled_caught:
logging.warning("_resolve_candidate._chat timeout, skipping...") logging.warning("_resolve_candidate._chat timeout, skipping...")

View File

@ -92,7 +92,7 @@ class CommunityReportsExtractor(Extractor):
text = perform_variable_replacements(self._extraction_prompt, variables=prompt_variables) text = perform_variable_replacements(self._extraction_prompt, variables=prompt_variables)
async with chat_limiter: async with chat_limiter:
try: try:
with trio.move_on_after(80) as cancel_scope: with trio.move_on_after(180) as cancel_scope:
response = await trio.to_thread.run_sync( self._chat, text, [{"role": "user", "content": "Output:"}], {}) response = await trio.to_thread.run_sync( self._chat, text, [{"role": "user", "content": "Output:"}], {})
if cancel_scope.cancelled_caught: if cancel_scope.cancelled_caught:
logging.warning("extract_community_report._chat timeout, skipping...") logging.warning("extract_community_report._chat timeout, skipping...")

View File

@ -57,20 +57,22 @@ async def run_graphrag(
): ):
chunks.append(d["content_with_weight"]) chunks.append(d["content_with_weight"])
subgraph = await generate_subgraph( with trio.fail_after(len(chunks)*60):
LightKGExt subgraph = await generate_subgraph(
if "method" not in row["kb_parser_config"].get("graphrag", {}) or row["kb_parser_config"]["graphrag"]["method"] != "general" LightKGExt
else GeneralKGExt, if "method" not in row["kb_parser_config"].get("graphrag", {}) or row["kb_parser_config"]["graphrag"]["method"] != "general"
tenant_id, else GeneralKGExt,
kb_id, tenant_id,
doc_id, kb_id,
chunks, doc_id,
language, chunks,
row["kb_parser_config"]["graphrag"].get("entity_types", []), language,
chat_model, row["kb_parser_config"]["graphrag"].get("entity_types", []),
embedding_model, chat_model,
callback, embedding_model,
) callback,
)
if not subgraph: if not subgraph:
return return
@ -125,7 +127,6 @@ async def run_graphrag(
return return
@timeout(60*60, 1)
async def generate_subgraph( async def generate_subgraph(
extractor: Extractor, extractor: Extractor,
tenant_id: str, tenant_id: str,

View File

@ -520,7 +520,7 @@ async def run_raptor(row, chat_mdl, embd_mdl, vector_size, callback=None):
return res, tk_count return res, tk_count
@timeout(60*60, 1) @timeout(60*60*2, 1)
async def do_handle_task(task): async def do_handle_task(task):
task_id = task["id"] task_id = task["id"]
task_from_page = task["from_page"] task_from_page = task["from_page"]