fc / apps /litigation_ai /services /draft_service.py
jun2024's picture
Upload 2241 files
b4f2238 verified
Raw History Blame Contribute Delete
5.64 kB
"""
诉讼文书草稿生成服务
提供诉讼文书草稿的生成功能.
Requirements: 2.4
"""
import logging
from collections.abc import Callable
from typing import Any
from apps.litigation_ai.models import LitigationSession
logger = logging.getLogger("apps.litigation_ai")
class DraftService:
"""
草稿生成服务(简化版,供 Agent 工具调用)
"""
def generate_draft_for_agent(
self,
case_id: int,
document_type: str,
litigation_goal: str,
evidence_context: str,
) -> dict[str, Any]:
"""
生成诉讼文书草稿(供 Agent 工具调用)
Args:
case_id: 案件 ID
document_type: 文书类型
litigation_goal: 诉讼目标
evidence_context: 证据上下文摘要
Returns:
生成结果,包含 display_text, draft, model 等字段
"""
import asyncio
from apps.litigation_ai.chains import LitigationDraftChain
from .context_service import LitigationContextService
context_service = LitigationContextService()
case_info = context_service.build_case_info(case_id, document_type)
chain = LitigationDraftChain()
# 同步执行异步方法
try:
loop = asyncio.get_event_loop()
except RuntimeError:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
result = loop.run_until_complete(
chain.arun(
case_info=case_info,
document_type=document_type,
litigation_goal=litigation_goal,
evidence_text=evidence_context,
)
)
return {
"display_text": result.display_text,
"draft": result.draft,
"model": result.model,
}
class LitigationDraftService:
async def generate_draft_async(
self,
*,
case_id: int,
session_id: str,
document_type: str,
litigation_goal: str,
evidence_list_ids: list[int],
evidence_item_ids: list[int],
our_evidence_item_ids: list[int] | None = None,
opponent_evidence_item_ids: list[int] | None = None,
stream_callback: Callable[[str], Any] | None = None,
) -> dict[str, Any]:
from asgiref.sync import sync_to_async
from apps.litigation_ai.chains import LitigationDraftChain
from .context_service import LitigationContextService
from .evidence_digest_service import EvidenceDigestService
context_service = LitigationContextService()
evidence_service = EvidenceDigestService()
case_info = await sync_to_async(context_service.build_case_info)(case_id, document_type)
our_evidence_item_ids = our_evidence_item_ids or []
opponent_evidence_item_ids = opponent_evidence_item_ids or []
evidence_text = await sync_to_async(evidence_service.build_evidence_text)(evidence_list_ids, evidence_item_ids)
if document_type in ["defense", "counterclaim_defense"]:
our_text = await sync_to_async(evidence_service.build_evidence_text)([], our_evidence_item_ids)
opponent_text = await sync_to_async(evidence_service.build_evidence_text)([], opponent_evidence_item_ids)
parts = []
if opponent_text:
parts.extend(["# 对方证据摘要", opponent_text, ""])
if our_text:
parts.extend(["# 我方证据摘要", our_text, ""])
evidence_text = "\n".join(parts).strip() or evidence_text
rag_ids = evidence_item_ids
if document_type in ["defense", "counterclaim_defense"]:
rag_ids = list(dict.fromkeys(opponent_evidence_item_ids + our_evidence_item_ids))
if rag_ids:
from .evidence_rag_service import EvidenceRAGService
rag = EvidenceRAGService()
await sync_to_async(rag.ensure_ingested)(rag_ids)
retrieved = await sync_to_async(rag.retrieve)(
f"{document_type};{case_info.get('cause_of_action', '')};{litigation_goal}",
rag_ids,
5,
)
if retrieved:
evidence_text = "\n".join(
[
evidence_text,
"",
"# 证据摘录(检索匹配)",
*[
f"[证据#{c.evidence_item_id} p{c.page_start}] {c.text[:500]}".strip()
for c in retrieved
if c.text
],
]
).strip()
chain = LitigationDraftChain()
result = await chain.arun(
case_info=case_info,
document_type=document_type,
litigation_goal=litigation_goal,
evidence_text=evidence_text,
stream_callback=stream_callback,
)
await sync_to_async(self._persist_draft)(session_id, result.draft)
return {
"display_text": result.display_text,
"draft": result.draft,
"model": result.model,
"token_usage": result.token_usage,
}
def _persist_draft(self, session_id: str, draft: dict[str, Any]) -> None:
session = LitigationSession.objects.filter(session_id=session_id).first()
if not session:
return
metadata = session.metadata or {}
metadata["draft"] = draft
session.metadata = metadata
session.save(update_fields=["metadata"])