diff --git a/backend/app/api/chat.py b/backend/app/api/chat.py index c58f3576..ad436c44 100644 --- a/backend/app/api/chat.py +++ b/backend/app/api/chat.py @@ -20,6 +20,13 @@ ROUTE_PERMISSION_ACTIONS = { "stream": "chat:stream", } +BUSINESS_AUXILIARY_PROMPT_KEYS = { + "obligation_extraction": "obligation_extraction_default", + "filing_materials_checklist": "filing_materials_checklist_default", + "negotiation_strategy": "negotiation_strategy_default", + "legal_opinion_boundary_fallback": "legal_opinion_boundary_fallback_default", +} + def get_chat_review_service(db: Session = Depends(get_db_session)) -> ReviewService: return ReviewService(db) @@ -60,14 +67,14 @@ def stream_chat( legal_article_service, ) review_context = _enrich_review_context_with_runtime_legal_sources(review_context, runtime_legal_sources) - prompt_runtime = _resolve_chat_prompt_runtime(current_user, review_context, prompt_runtime_service) + prompt_runtime = _resolve_chat_prompt_runtime(current_user, review_context, prompt_runtime_service, payload.message) review_context = _enrich_review_context_with_prompt_runtime(review_context, prompt_runtime, prompt_runtime_service) template_key = prompt_runtime.get("template_key") if prompt_runtime and prompt_runtime.get("available") else None if prompt_runtime_service is not None: prompt_runtime_service.record_run_link( current_user, prompt_runtime, - run_type="legal_chat", + run_type=str((prompt_runtime or {}).get("prompt_type") or "legal_chat"), run_id=payload.conversation_id or "new_conversation", resource_type="conversation", resource_id=payload.conversation_id, @@ -98,10 +105,21 @@ def _resolve_chat_prompt_runtime( current_user: Dict[str, Any], review_context: Optional[Dict[str, Any]], prompt_runtime_service: Optional[PromptRuntimeService], + message: str = "", ) -> Dict[str, Any]: if prompt_runtime_service is None: return {"available": False, "prompt_type": "legal_chat", "prompt_version": "legal_chat.shared_ai_stream.v1", "source": "local_default"} has_review_context = bool(review_context and ((review_context.get("reviewId") or review_context.get("review_id")))) + business_auxiliary_key = _detect_business_auxiliary_prompt_key(message, review_context) + if business_auxiliary_key: + return prompt_runtime_service.resolve_published_prompt( + current_user, + "business_auxiliary", + preferred_keys=[ + business_auxiliary_key, + ], + fallback_prompt_version="business_auxiliary.shared_ai_stream.v1", + ) return prompt_runtime_service.resolve_published_prompt( current_user, "legal_chat", @@ -113,6 +131,38 @@ def _resolve_chat_prompt_runtime( ) +def _detect_business_auxiliary_prompt_key( + message: str, + review_context: Optional[Dict[str, Any]], +) -> Optional[str]: + text = _build_prompt_intent_text(message, review_context) + if _contains_any(text, ["法律意见书强边界", "法律意见书兜底", "法律意见书边界", "legal opinion boundary", "legal opinion fallback"]): + return BUSINESS_AUXILIARY_PROMPT_KEYS["legal_opinion_boundary_fallback"] + if _contains_any(text, ["履约义务", "履行义务", "义务提取", "履约清单", "obligation extraction", "performance obligation"]): + return BUSINESS_AUXILIARY_PROMPT_KEYS["obligation_extraction"] + if _contains_any(text, ["工商", "备案材料", "变更登记", "材料清单", "filing materials", "registration checklist", "filing checklist"]): + return BUSINESS_AUXILIARY_PROMPT_KEYS["filing_materials_checklist"] + if _contains_any(text, ["谈判策略", "谈判建议", "怎么谈", "议价", "让步方案", "negotiation strategy", "negotiate"]): + return BUSINESS_AUXILIARY_PROMPT_KEYS["negotiation_strategy"] + if _contains_any(text, ["法律意见书", "legal opinion"]) and _contains_any( + text, + ["边界", "兜底", "免责声明", "不能替代", "人工复核", "boundary", "fallback", "disclaimer", "human review"], + ): + return BUSINESS_AUXILIARY_PROMPT_KEYS["legal_opinion_boundary_fallback"] + return None + + +def _build_prompt_intent_text(message: str, review_context: Optional[Dict[str, Any]]) -> str: + parts = [message or ""] + if isinstance(review_context, dict): + parts.append(json.dumps(review_context, ensure_ascii=False, default=str)) + return "\n".join(parts).lower() + + +def _contains_any(value: str, candidates: Iterable[str]) -> bool: + return any(candidate.lower() in value for candidate in candidates) + + def _enrich_review_context_with_prompt_runtime( review_context: Optional[Dict[str, Any]], prompt_runtime: Optional[Dict[str, Any]], diff --git a/backend/app/services/prompt_asset_service.py b/backend/app/services/prompt_asset_service.py index a499d324..cb3d4fbe 100644 --- a/backend/app/services/prompt_asset_service.py +++ b/backend/app/services/prompt_asset_service.py @@ -26,6 +26,7 @@ class PromptAssetService: "legal_chat", "wording_rewrite", "regulation_impact", + "business_auxiliary", } EVALUATION_STATUSES = {"not_evaluated", "pending", "passed", "failed"} PUBLISHABLE_EVALUATION_STATUSES = {"passed"} @@ -36,6 +37,7 @@ class PromptAssetService: "clause_recommendation": {"suite_key": "phase13_clause_generation", "sample_count": 6}, "wording_rewrite": {"suite_key": "phase15_wording_rewrite", "sample_count": 3}, "regulation_impact": {"suite_key": "future_regulation_impact", "sample_count": 0}, + "business_auxiliary": {"suite_key": "future_business_auxiliary", "sample_count": 0}, } def __init__(self, db: Session): @@ -559,7 +561,7 @@ class PromptAssetService: "detail": f"referenced={len(mentioned_variables)} declared={len(variable_names)}", } ) - if asset.prompt_type in {"contract_review", "clause_recommendation", "wording_rewrite"}: + if asset.prompt_type in {"contract_review", "clause_recommendation", "wording_rewrite", "business_auxiliary"}: checks.append( { "key": "risk_boundary_instruction", diff --git a/backend/app/services/prompt_golden_sample_evaluator.py b/backend/app/services/prompt_golden_sample_evaluator.py index 6f28a718..c6be468a 100644 --- a/backend/app/services/prompt_golden_sample_evaluator.py +++ b/backend/app/services/prompt_golden_sample_evaluator.py @@ -47,6 +47,11 @@ class PromptGoldenSampleEvaluator: "sample_family": "future_regulation_impact", "min_samples": 0, }, + "business_auxiliary": { + "suite_key": "future_business_auxiliary", + "sample_family": "future_business_auxiliary", + "min_samples": 0, + }, } def __init__( @@ -199,6 +204,8 @@ class PromptGoldenSampleEvaluator: return [self._kb_qa_sample(row) for row in self._read_phase13_csv("kb-qa-golden-sample-inventory.csv")] if prompt_type == "wording_rewrite": return self._wording_rewrite_samples() + if prompt_type == "business_auxiliary": + return [] return [] def _evaluate_sample_with_llm( diff --git a/backend/tests/test_chat_api.py b/backend/tests/test_chat_api.py index f42cbefb..b281eb52 100644 --- a/backend/tests/test_chat_api.py +++ b/backend/tests/test_chat_api.py @@ -5,6 +5,8 @@ from fastapi import HTTPException from fastapi.testclient import TestClient from app.api.chat import ( + _detect_business_auxiliary_prompt_key, + _resolve_chat_prompt_runtime, get_chat_legal_article_service, get_chat_prompt_runtime_service, get_chat_review_service, @@ -121,17 +123,28 @@ class StubTenantService: class StubPromptRuntimeService: def __init__(self): self.record_calls = [] + self.resolve_calls = [] def resolve_published_prompt(self, current_user, prompt_type, *, preferred_keys=None, fallback_prompt_version=None): + preferred_keys = [key for key in (preferred_keys or []) if key] + self.resolve_calls.append( + { + "current_user": current_user, + "prompt_type": prompt_type, + "preferred_keys": preferred_keys, + "fallback_prompt_version": fallback_prompt_version, + } + ) + selected_key = preferred_keys[0] if preferred_keys else "legal_chat_default" return { "available": True, "prompt_asset_id": "prompt-001", "prompt_asset_version_id": "promptver-001", - "prompt_key": "legal_chat_default", + "prompt_key": selected_key, "prompt_type": prompt_type, "version_label": "v1.0", - "prompt_version": "legal_chat_default.v1.0", - "template_key": "legal_chat_default", + "prompt_version": f"{selected_key}.v1.0", + "template_key": selected_key, "source": "published_prompt_asset", } @@ -240,6 +253,37 @@ class ChatApiTestCase(unittest.TestCase): self.assertEqual(review_context["promptRuntime"]["prompt_version"], "legal_chat_default.v1.0") self.assertEqual(prompt_runtime_service.record_calls[0][2]["run_type"], "legal_chat") + def test_stream_chat_routes_business_auxiliary_intent_to_specialized_prompt(self): + app.dependency_overrides[require_current_user] = lambda: {"id": "user-1", "tenant_id": "tenant-1"} + prompt_runtime_service = StubPromptRuntimeService() + app.dependency_overrides[get_chat_prompt_runtime_service] = lambda: prompt_runtime_service + + response = self.client.post("/api/v1/chat/stream", json={"message": "请提取这份合同的履约义务并列出证据"}) + + self.assertEqual(response.status_code, 200) + self.assertEqual(prompt_runtime_service.resolve_calls[0]["prompt_type"], "business_auxiliary") + self.assertEqual(prompt_runtime_service.resolve_calls[0]["preferred_keys"][0], "obligation_extraction_default") + self.assertEqual(self.chat_service.stream_calls[0][4], "obligation_extraction_default") + self.assertEqual(prompt_runtime_service.record_calls[0][2]["run_type"], "business_auxiliary") + self.assertEqual(_detect_business_auxiliary_prompt_key("请提取这份合同的履约义务并列出证据", None), "obligation_extraction_default") + self.assertEqual(_detect_business_auxiliary_prompt_key("请列出工商备案材料清单", None), "filing_materials_checklist_default") + self.assertEqual(_detect_business_auxiliary_prompt_key("请给我谈判策略", None), "negotiation_strategy_default") + self.assertEqual(_detect_business_auxiliary_prompt_key("法律意见书强边界兜底怎么写", None), "legal_opinion_boundary_fallback_default") + self.assertEqual( + _resolve_chat_prompt_runtime({"id": "user-1", "tenant_id": "tenant-1"}, None, prompt_runtime_service, "请给我谈判策略"), + { + "available": True, + "prompt_asset_id": "prompt-001", + "prompt_asset_version_id": "promptver-001", + "prompt_key": "negotiation_strategy_default", + "prompt_type": "business_auxiliary", + "version_label": "v1.0", + "prompt_version": "negotiation_strategy_default.v1.0", + "template_key": "negotiation_strategy_default", + "source": "published_prompt_asset", + }, + ) + def test_stream_chat_adds_review_legal_article_sources(self): app.dependency_overrides[require_current_user] = lambda: {"id": "user-1", "tenant_id": "tenant-1"} app.dependency_overrides[get_chat_review_service] = lambda: StubReviewService() diff --git a/backend/tests/test_prompt_asset_service.py b/backend/tests/test_prompt_asset_service.py index 667bfa77..d15aec1b 100644 --- a/backend/tests/test_prompt_asset_service.py +++ b/backend/tests/test_prompt_asset_service.py @@ -235,6 +235,12 @@ class PromptAssetServiceTestCase(unittest.TestCase): "software_saas_default", "labor_service_default", } + business_keys = { + "obligation_extraction_default", + "filing_materials_checklist_default", + "negotiation_strategy_default", + "legal_opinion_boundary_fallback_default", + } review_keys = { "contract_review_investment_finance", "contract_review_corporate_governance", @@ -245,11 +251,17 @@ class PromptAssetServiceTestCase(unittest.TestCase): } self.assertTrue(REQUIRED_PROMPT_KEYS.issubset(set(assets_by_key))) + self.assertIn("business_auxiliary", self.service.PROMPT_TYPES) for prompt_key in generation_keys: asset = assets_by_key[prompt_key] self.assertEqual(asset["prompt_type"], "contract_generation") self.assertIn("generate", asset["prompt_content"].lower()) self.assertEqual(asset["model_config"]["temperature"], 0.2) + for prompt_key in business_keys: + asset = assets_by_key[prompt_key] + self.assertEqual(asset["prompt_type"], "business_auxiliary") + self.assertIn("output", asset["prompt_content"].lower()) + self.assertIn(asset["model_config"]["temperature"], {0.1, 0.2}) for prompt_key in review_keys: asset = assets_by_key[prompt_key] self.assertEqual(asset["prompt_type"], "contract_review") @@ -305,12 +317,22 @@ class PromptAssetServiceTestCase(unittest.TestCase): self.assertEqual(evaluation["evaluation_report"]["evaluation_mode"], "llm") self.assertGreaterEqual(evaluation["evaluation_run"]["sample_count"], 3) self.assertEqual(len(fake_llm_client.calls), evaluation["evaluation_run"]["sample_count"]) - self.assertEqual( - evaluation["evaluation_report"]["model_invocation"]["sample_invocation_count"], - evaluation["evaluation_run"]["sample_count"], + + def test_business_auxiliary_prompt_evaluation_uses_future_suite(self): + created = self._create_asset( + evaluation=False, + prompt_key="obligation_extraction_default", + prompt_type="business_auxiliary", + name="Obligation extraction", + prompt_content="Extract obligations, output JSON, risk boundary, legal law source article citation.", ) - self.assertTrue(all(item["evaluator_mode"] == "llm" for item in evaluation["evaluation_report"]["sample_results"])) - self.assertTrue(all(call["current_user"]["id"] == self.admin_user["id"] for call in fake_llm_client.calls)) + + evaluation = self.service.evaluate_current_prompt_asset(self.admin_user, created["id"]) + + self.assertEqual(evaluation["version"]["evaluation_status"], "passed") + self.assertEqual(evaluation["evaluation_report"]["suite_key"], "future_business_auxiliary") + self.assertEqual(evaluation["evaluation_report"]["sample_count"], 0) + self.assertEqual(evaluation["evaluation_report"]["evaluation_mode"], "local_fallback") def test_publish_with_report_and_create_next_version(self): created = self._create_asset(evaluation=False) diff --git a/backend/tests/test_prompt_assets_api.py b/backend/tests/test_prompt_assets_api.py index ff6d7629..f04d51c2 100644 --- a/backend/tests/test_prompt_assets_api.py +++ b/backend/tests/test_prompt_assets_api.py @@ -57,7 +57,7 @@ class StubPromptAssetService: "page": page, "page_size": page_size, "total": 1, - "prompt_types": ["contract_generation", "contract_review"], + "prompt_types": ["business_auxiliary", "contract_generation", "contract_review"], } def get_prompt_asset_detail(self, current_user, asset_id): diff --git a/backend/tools/asset_inventory_gap_report.py b/backend/tools/asset_inventory_gap_report.py index f8b64681..3837e657 100644 --- a/backend/tools/asset_inventory_gap_report.py +++ b/backend/tools/asset_inventory_gap_report.py @@ -45,6 +45,7 @@ REQUIRED_PROMPT_TYPES = [ "clause_recommendation", "wording_rewrite", "regulation_impact", + "business_auxiliary", ] REQUIRED_PROMPT_KEYS = [ @@ -80,6 +81,10 @@ REQUIRED_PROMPT_KEYS = [ "clause_recommendation_default", "wording_rewrite_default", "regulation_impact_default", + "obligation_extraction_default", + "filing_materials_checklist_default", + "negotiation_strategy_default", + "legal_opinion_boundary_fallback_default", ] INVENTORY_FILES = { diff --git a/backend/tools/seed_prompt_assets.py b/backend/tools/seed_prompt_assets.py index 0e698b54..bb750665 100644 --- a/backend/tools/seed_prompt_assets.py +++ b/backend/tools/seed_prompt_assets.py @@ -17,6 +17,7 @@ REQUIRED_PROMPT_TYPES = { "clause_recommendation", "wording_rewrite", "regulation_impact", + "business_auxiliary", } REQUIRED_PROMPT_KEYS = { @@ -52,6 +53,10 @@ REQUIRED_PROMPT_KEYS = { "clause_recommendation_default", "wording_rewrite_default", "regulation_impact_default", + "obligation_extraction_default", + "filing_materials_checklist_default", + "negotiation_strategy_default", + "legal_opinion_boundary_fallback_default", } diff --git a/frontend/src/app/prompt-assets/page.tsx b/frontend/src/app/prompt-assets/page.tsx index eb0b05bc..5ea51e3a 100644 --- a/frontend/src/app/prompt-assets/page.tsx +++ b/frontend/src/app/prompt-assets/page.tsx @@ -64,6 +64,7 @@ const promptTypeOptions: Array<{ value: PromptAssetType; label: string }> = [ { value: "legal_chat", label: "法规问答" }, { value: "wording_rewrite", label: "措辞改写" }, { value: "regulation_impact", label: "法规影响分析" }, + { value: "business_auxiliary", label: "业务辅助" }, ]; const statusOptions = [ diff --git a/frontend/src/types/api.ts b/frontend/src/types/api.ts index f7d24cfc..b4ca4aa7 100644 --- a/frontend/src/types/api.ts +++ b/frontend/src/types/api.ts @@ -520,7 +520,8 @@ export type PromptAssetType = | "clause_recommendation" | "legal_chat" | "wording_rewrite" - | "regulation_impact"; + | "regulation_impact" + | "business_auxiliary"; export type PromptAssetItem = { id: string; diff --git a/project-docs/AI合同起草与审查助手-当前工作进度保存-2026-05-11.md b/project-docs/AI合同起草与审查助手-当前工作进度保存-2026-05-11.md index 504b4eea..07c427ac 100644 --- a/project-docs/AI合同起草与审查助手-当前工作进度保存-2026-05-11.md +++ b/project-docs/AI合同起草与审查助手-当前工作进度保存-2026-05-11.md @@ -5215,3 +5215,22 @@ - `python -m json.tool project-docs\phase15-prompt-assets\default-prompt-assets.json | Out-Null` - `python -m py_compile backend\app\services\contract_generation_service.py backend\tools\seed_prompt_assets.py backend\tools\asset_inventory_gap_report.py backend\tests\test_prompt_asset_service.py backend\tests\test_contracts_api.py` - `$env:PYTHONPATH='backend'; python -m unittest backend.tests.test_prompt_asset_service backend.tests.test_prompt_runtime_service backend.tests.test_prompt_assets_api backend.tests.test_contracts_api -v` + +## 2026-05-24 Phase15 业务辅助 Prompt 缺口闭环 + +- 本轮新增 `business_auxiliary` Prompt 类型,用于承载不直接属于起草、审查、条款推荐、措辞改写或法规影响分析的业务辅助任务。 +- 补齐 4 个业务辅助 Prompt 资产: + - `obligation_extraction_default`:履约义务提取 Prompt + - `filing_materials_checklist_default`:工商/备案材料清单 Prompt + - `negotiation_strategy_default`:谈判策略 Prompt + - `legal_opinion_boundary_fallback_default`:法律意见书强边界兜底 Prompt +- `Chat` 运行入口已接入业务辅助意图识别: + - 命中履约义务、工商/备案材料、谈判策略、法律意见书强边界兜底等关键词时,优先解析 `business_auxiliary` 类型下的专项 Prompt。 + - 未命中业务辅助意图时继续走原有 `legal_chat_default` 或 `legal_chat_review` 路径。 +- `PromptAssetService`、`PromptGoldenSampleEvaluator`、默认种子脚本和缺口报告均已纳入 `business_auxiliary` 类型与上述 4 个必需 key。 +- 前端 Prompt 资产管理类型枚举已新增 `business_auxiliary`,页面下拉可创建/筛选业务辅助 Prompt。 +- 验证: + - `python -m json.tool project-docs\phase15-prompt-assets\default-prompt-assets.json | Out-Null` + - `python -m py_compile backend\app\api\chat.py backend\app\services\prompt_asset_service.py backend\app\services\prompt_golden_sample_evaluator.py backend\tools\seed_prompt_assets.py backend\tools\asset_inventory_gap_report.py backend\tests\test_prompt_asset_service.py backend\tests\test_chat_api.py backend\tests\test_prompt_assets_api.py` + - `$env:PYTHONPATH='backend'; python -m unittest backend.tests.test_prompt_asset_service backend.tests.test_prompt_assets_api backend.tests.test_chat_api backend.tests.test_prompt_runtime_service -v` + - `npm run lint`(frontend) diff --git a/project-docs/phase15-prompt-assets/default-prompt-assets.json b/project-docs/phase15-prompt-assets/default-prompt-assets.json index 920e9e33..d3bd01c5 100644 --- a/project-docs/phase15-prompt-assets/default-prompt-assets.json +++ b/project-docs/phase15-prompt-assets/default-prompt-assets.json @@ -355,6 +355,154 @@ }, "change_summary": "Phase15 默认法律问答 Prompt 正式种入" }, + { + "prompt_key": "obligation_extraction_default", + "prompt_type": "business_auxiliary", + "name": "履约义务提取 Prompt", + "description": "用于从合同文本、审查结果或业务背景中提取双方履约义务、期限、触发条件和证据留存要求。", + "target_scene": "合同履约管理与义务清单提取", + "system_prompt": "你是 AI 合同履约辅助助手。你只能基于输入的合同文本、审查上下文和法条来源提取义务,不得新增合同没有约定的事实。对无法确认的事项必须列入 missing_fields 或 verification_items。", + "prompt_content": "请 extract obligations from contract_text={{contract_text}},review_context={{review_context}},party_position={{party_position}},legal_article_refs={{legal_article_refs}}。输出 return JSON,字段包括 obligations、timeline、evidence_requirements、risk_flags、missing_fields、verification_items、legal_basis、quality_notes。每项 obligations 必须包含 obligor、beneficiary、obligation_text、trigger_condition、deadline、performance_standard、evidence_to_keep、breach_consequence、source_clause、risk_boundary。必须标注 legal law source article citation,并说明不确定项。output return JSON risk boundary legal law source article citation", + "variables": [ + { "name": "contract_text", "required": true, "description": "待提取义务的合同或法律文书文本" }, + { "name": "review_context", "required": false, "description": "审查结果或业务上下文" }, + { "name": "party_position", "required": false, "description": "提取视角,例如甲方、乙方、平台方、投资方" }, + { "name": "legal_article_refs", "required": false, "description": "相关法条来源列表" } + ], + "output_schema": { + "type": "object", + "required": ["obligations", "missing_fields", "legal_basis"], + "properties": { + "obligations": { "type": "array" }, + "timeline": { "type": "array" }, + "evidence_requirements": { "type": "array" }, + "risk_flags": { "type": "array" }, + "missing_fields": { "type": "array" }, + "verification_items": { "type": "array" }, + "legal_basis": { "type": "array" }, + "quality_notes": { "type": "array" } + } + }, + "model_config": { + "provider": "shared-ai-platform", + "model": "platform-default", + "temperature": 0.1 + }, + "change_summary": "补齐业务辅助履约义务提取 Prompt" + }, + { + "prompt_key": "filing_materials_checklist_default", + "prompt_type": "business_auxiliary", + "name": "工商/备案材料清单 Prompt", + "description": "用于根据交易、公司治理或变更事项输出工商登记、备案、内部审批和材料准备清单。", + "target_scene": "工商登记备案材料清单生成", + "system_prompt": "你是 AI 工商备案材料辅助助手。你必须区分内部审批材料、工商登记材料、备案材料、签署文件和待人工核验事项。不得承诺登记机关一定受理或通过。", + "prompt_content": "请 generate filing materials checklist。matter_type={{matter_type}},document_type_code={{document_type_code}},contract_text={{contract_text}},company_context={{company_context}},legal_article_refs={{legal_article_refs}}。输出 return JSON,字段包括 matter_summary、preconditions、materials、signing_requirements、filing_authority、sequence、missing_fields、verification_items、risk_boundary、legal_basis。materials 每项必须包含 material_name、purpose、provider、signatory_or_seal、copy_or_original、required_or_optional、notes。必须标注 legal law source article citation,说明工商/备案口径可能因地区和登记机关要求变化。output return JSON risk boundary legal law source article citation", + "variables": [ + { "name": "matter_type", "required": false, "description": "事项类型,例如股权转让、增资、章程修订、法定代表人变更" }, + { "name": "document_type_code", "required": false, "description": "文书类型编码" }, + { "name": "contract_text", "required": false, "description": "合同或决议文本" }, + { "name": "company_context", "required": false, "description": "公司主体、股东、章程和登记背景" }, + { "name": "legal_article_refs", "required": false, "description": "相关法条来源列表" } + ], + "output_schema": { + "type": "object", + "required": ["materials", "missing_fields", "legal_basis"], + "properties": { + "matter_summary": { "type": "string" }, + "preconditions": { "type": "array" }, + "materials": { "type": "array" }, + "signing_requirements": { "type": "array" }, + "filing_authority": { "type": "string" }, + "sequence": { "type": "array" }, + "missing_fields": { "type": "array" }, + "verification_items": { "type": "array" }, + "risk_boundary": { "type": "string" }, + "legal_basis": { "type": "array" } + } + }, + "model_config": { + "provider": "shared-ai-platform", + "model": "platform-default", + "temperature": 0.1 + }, + "change_summary": "补齐业务辅助工商备案材料清单 Prompt" + }, + { + "prompt_key": "negotiation_strategy_default", + "prompt_type": "business_auxiliary", + "name": "谈判策略 Prompt", + "description": "用于根据合同文本、风险审查结果和我方立场输出可执行的谈判策略、底线、让步阶梯和备选条款。", + "target_scene": "合同谈判策略与条款改写建议", + "system_prompt": "你是 AI 合同谈判策略助手。你必须把商业目标、法律风险、证据条件和谈判筹码分开表达,不得建议违法、失衡或无法履行的条款。", + "prompt_content": "请 provide negotiation strategy。contract_text={{contract_text}},review_context={{review_context}},party_position={{party_position}},business_goal={{business_goal}},legal_article_refs={{legal_article_refs}}。输出 return JSON,字段包括 strategy_summary、must_hold_positions、negotiable_positions、concession_ladder、fallback_clauses、red_flags、talking_points、risk_boundaries、legal_basis、next_actions。必须说明 negotiate strategy risk boundary,给出可落地话术和备选条款,但不得删除法定义务或必要责任边界。必须标注 legal law source article citation。output return JSON risk boundary negotiate legal law source article citation", + "variables": [ + { "name": "contract_text", "required": false, "description": "合同文本或关键条款" }, + { "name": "review_context", "required": false, "description": "审查结果或风险项" }, + { "name": "party_position", "required": false, "description": "谈判立场,例如甲方、乙方、投资方、融资方" }, + { "name": "business_goal", "required": false, "description": "业务目标和谈判优先级" }, + { "name": "legal_article_refs", "required": false, "description": "相关法条来源列表" } + ], + "output_schema": { + "type": "object", + "required": ["strategy_summary", "must_hold_positions", "risk_boundaries", "legal_basis"], + "properties": { + "strategy_summary": { "type": "string" }, + "must_hold_positions": { "type": "array" }, + "negotiable_positions": { "type": "array" }, + "concession_ladder": { "type": "array" }, + "fallback_clauses": { "type": "array" }, + "red_flags": { "type": "array" }, + "talking_points": { "type": "array" }, + "risk_boundaries": { "type": "array" }, + "legal_basis": { "type": "array" }, + "next_actions": { "type": "array" } + } + }, + "model_config": { + "provider": "shared-ai-platform", + "model": "platform-default", + "temperature": 0.2 + }, + "change_summary": "补齐业务辅助谈判策略 Prompt" + }, + { + "prompt_key": "legal_opinion_boundary_fallback_default", + "prompt_type": "business_auxiliary", + "name": "法律意见书强边界兜底 Prompt", + "description": "用于法律意见书场景下材料不足、事实未核验或风险过高时输出强边界兜底说明和人工复核清单。", + "target_scene": "法律意见书边界兜底与人工复核", + "system_prompt": "你是 AI 法律意见书边界兜底助手。你不得替代律师出具最终法律意见,不得对未核验事实作确定性结论。必须优先输出边界、假设、无法判断事项和人工复核要求。", + "prompt_content": "请 generate legal opinion boundary fallback。matter_summary={{matter_summary}},facts={{facts}},materials={{materials}},draft_opinion={{draft_opinion}},legal_article_refs={{legal_article_refs}}。输出 return JSON,字段包括 boundary_notice、assumptions、cannot_conclude_items、missing_materials、human_review_required、safe_response、risk_boundary、legal_basis、next_actions。必须明确:AI 输出仅为辅助草稿,不构成正式法律意见;材料不足时只能给出条件性意见或拒绝确定性结论。必须标注 legal law source article citation。output return JSON risk boundary fallback legal law source article citation", + "variables": [ + { "name": "matter_summary", "required": false, "description": "事项概述" }, + { "name": "facts", "required": false, "description": "已知事实和待核验事实" }, + { "name": "materials", "required": false, "description": "用户提供的材料清单" }, + { "name": "draft_opinion", "required": false, "description": "已有法律意见书草稿或拟输出内容" }, + { "name": "legal_article_refs", "required": false, "description": "相关法条来源列表" } + ], + "output_schema": { + "type": "object", + "required": ["boundary_notice", "cannot_conclude_items", "human_review_required", "legal_basis"], + "properties": { + "boundary_notice": { "type": "string" }, + "assumptions": { "type": "array" }, + "cannot_conclude_items": { "type": "array" }, + "missing_materials": { "type": "array" }, + "human_review_required": { "type": "array" }, + "safe_response": { "type": "string" }, + "risk_boundary": { "type": "string" }, + "legal_basis": { "type": "array" }, + "next_actions": { "type": "array" } + } + }, + "model_config": { + "provider": "shared-ai-platform", + "model": "platform-default", + "temperature": 0.1 + }, + "change_summary": "补齐业务辅助法律意见书强边界兜底 Prompt" + }, { "prompt_key": "clause_recommendation_default", "prompt_type": "clause_recommendation",