feat(ontology): make entity/edge type limits configurable via env vars
Revert default limits back to 10 edges and 12 entities (10 specific + 2 fallback), matching Zep Cloud's maximum. Expose ONTOLOGY_MAX_ENTITY_TYPES and ONTOLOGY_MAX_EDGE_TYPES in Config so operators can override without touching code. Prompts now inject the live values at request time. Also replace Chinese comments in .env.example with English equivalents. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
0ce4d6c10e
commit
ba9c8d1f42
|
|
@ -41,8 +41,12 @@ ZEP_API_KEY=your_zep_api_key_here
|
||||||
# LLM_SMALL_BASE_URL=https://<resource>.cognitiveservices.azure.com/openai/deployments/<small-model>/chat/completions?api-version=2024-05-01-preview
|
# LLM_SMALL_BASE_URL=https://<resource>.cognitiveservices.azure.com/openai/deployments/<small-model>/chat/completions?api-version=2024-05-01-preview
|
||||||
# LLM_SMALL_MODEL_NAME=gpt-4o-mini
|
# LLM_SMALL_MODEL_NAME=gpt-4o-mini
|
||||||
|
|
||||||
# ===== 加速 LLM 配置(可选)=====
|
# ===== Ontology limits =====
|
||||||
# 注意如果不使用加速配置,env文件中就不要出现下面的配置项
|
# ONTOLOGY_MAX_ENTITY_TYPES=12 # total entity types (specific + 2 fallback); Zep Cloud max is 10 specific + 2 = 12
|
||||||
|
# ONTOLOGY_MAX_EDGE_TYPES=10 # max relationship types; Zep Cloud max is 10
|
||||||
|
|
||||||
|
# ===== Boost LLM (optional) =====
|
||||||
|
# Secondary faster LLM — omit these lines entirely if not used
|
||||||
LLM_BOOST_API_KEY=your_api_key_here
|
LLM_BOOST_API_KEY=your_api_key_here
|
||||||
LLM_BOOST_BASE_URL=your_base_url_here
|
LLM_BOOST_BASE_URL=your_base_url_here
|
||||||
LLM_BOOST_MODEL_NAME=your_model_name_here
|
LLM_BOOST_MODEL_NAME=your_model_name_here
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,18 @@ class Config:
|
||||||
LLM_BASE_URL = os.environ.get('LLM_BASE_URL', 'https://api.openai.com/v1')
|
LLM_BASE_URL = os.environ.get('LLM_BASE_URL', 'https://api.openai.com/v1')
|
||||||
LLM_MODEL_NAME = os.environ.get('LLM_MODEL_NAME', 'gpt-4o-mini')
|
LLM_MODEL_NAME = os.environ.get('LLM_MODEL_NAME', 'gpt-4o-mini')
|
||||||
|
|
||||||
|
# Embedding LLM (used by Graphiti for vector indexing)
|
||||||
|
# Falls back to LLM_* values if not set
|
||||||
|
LLM_EMBED_API_KEY = os.environ.get('LLM_EMBED_API_KEY') or os.environ.get('LLM_API_KEY')
|
||||||
|
LLM_EMBED_BASE_URL = os.environ.get('LLM_EMBED_BASE_URL') or os.environ.get('LLM_BASE_URL', 'https://api.openai.com/v1')
|
||||||
|
LLM_EMBED_MODEL_NAME = os.environ.get('LLM_EMBED_MODEL_NAME', 'text-embedding-3-small')
|
||||||
|
|
||||||
|
# Small/fast LLM (used by Graphiti for lightweight tasks like reranking)
|
||||||
|
# Falls back to LLM_* values if not set
|
||||||
|
LLM_SMALL_API_KEY = os.environ.get('LLM_SMALL_API_KEY') or os.environ.get('LLM_API_KEY')
|
||||||
|
LLM_SMALL_BASE_URL = os.environ.get('LLM_SMALL_BASE_URL') or os.environ.get('LLM_BASE_URL', 'https://api.openai.com/v1')
|
||||||
|
LLM_SMALL_MODEL_NAME = os.environ.get('LLM_SMALL_MODEL_NAME') or os.environ.get('LLM_MODEL_NAME', 'gpt-4o-mini')
|
||||||
|
|
||||||
# Graph backend: "zep" (default, cloud) o "graphiti" (Neo4j local)
|
# Graph backend: "zep" (default, cloud) o "graphiti" (Neo4j local)
|
||||||
GRAPH_BACKEND = os.environ.get('GRAPH_BACKEND', 'zep')
|
GRAPH_BACKEND = os.environ.get('GRAPH_BACKEND', 'zep')
|
||||||
|
|
||||||
|
|
@ -43,6 +55,7 @@ class Config:
|
||||||
NEO4J_URI = os.environ.get('NEO4J_URI', 'bolt://localhost:7687')
|
NEO4J_URI = os.environ.get('NEO4J_URI', 'bolt://localhost:7687')
|
||||||
NEO4J_USER = os.environ.get('NEO4J_USER', 'neo4j')
|
NEO4J_USER = os.environ.get('NEO4J_USER', 'neo4j')
|
||||||
NEO4J_PASSWORD = os.environ.get('NEO4J_PASSWORD')
|
NEO4J_PASSWORD = os.environ.get('NEO4J_PASSWORD')
|
||||||
|
GRAPHITI_BATCH_SIZE = int(os.environ.get('GRAPHITI_BATCH_SIZE', '10'))
|
||||||
|
|
||||||
# LLM provider ("" = OpenAI-compatible per defecte, "gemini" = Google AI Studio)
|
# LLM provider ("" = OpenAI-compatible per defecte, "gemini" = Google AI Studio)
|
||||||
LLM_PROVIDER = os.environ.get('LLM_PROVIDER', '')
|
LLM_PROVIDER = os.environ.get('LLM_PROVIDER', '')
|
||||||
|
|
@ -56,6 +69,10 @@ class Config:
|
||||||
DEFAULT_CHUNK_SIZE = 500 # default chunk size
|
DEFAULT_CHUNK_SIZE = 500 # default chunk size
|
||||||
DEFAULT_CHUNK_OVERLAP = 50 # default overlap size
|
DEFAULT_CHUNK_OVERLAP = 50 # default overlap size
|
||||||
|
|
||||||
|
# Ontology generation limits
|
||||||
|
ONTOLOGY_MAX_ENTITY_TYPES = int(os.environ.get('ONTOLOGY_MAX_ENTITY_TYPES', '12'))
|
||||||
|
ONTOLOGY_MAX_EDGE_TYPES = int(os.environ.get('ONTOLOGY_MAX_EDGE_TYPES', '10'))
|
||||||
|
|
||||||
# OASIS simulation settings
|
# OASIS simulation settings
|
||||||
OASIS_DEFAULT_MAX_ROUNDS = int(os.environ.get('OASIS_DEFAULT_MAX_ROUNDS', '10'))
|
OASIS_DEFAULT_MAX_ROUNDS = int(os.environ.get('OASIS_DEFAULT_MAX_ROUNDS', '10'))
|
||||||
OASIS_SIMULATION_DATA_DIR = os.path.join(os.path.dirname(__file__), '../uploads/simulations')
|
OASIS_SIMULATION_DATA_DIR = os.path.join(os.path.dirname(__file__), '../uploads/simulations')
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import re
|
||||||
from typing import Dict, Any, List, Optional
|
from typing import Dict, Any, List, Optional
|
||||||
from ..utils.llm_client import LLMClient
|
from ..utils.llm_client import LLMClient
|
||||||
from ..utils.locale import get_language_instruction, t
|
from ..utils.locale import get_language_instruction, t
|
||||||
|
from ..config import Config
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
@ -92,17 +93,17 @@ Please output JSON format with the following structure:
|
||||||
|
|
||||||
### 1. Entity Type Design — Must Be Strictly Followed
|
### 1. Entity Type Design — Must Be Strictly Followed
|
||||||
|
|
||||||
**Quantity requirement: exactly 20 entity types**
|
**Quantity requirement: see the mandatory rules in the user message**
|
||||||
|
|
||||||
**Hierarchy requirement (must include both specific types and fallback types)**:
|
**Hierarchy requirement (must include both specific types and fallback types)**:
|
||||||
|
|
||||||
Your 20 entity types must include the following levels:
|
Your entity types must include the following levels:
|
||||||
|
|
||||||
A. **Fallback types (required, placed as the last 2 in the list)**:
|
A. **Fallback types (required, placed as the last 2 in the list)**:
|
||||||
- `Person`: Fallback type for any individual person. Use this when a person does not fit any other more specific person type.
|
- `Person`: Fallback type for any individual person. Use this when a person does not fit any other more specific person type.
|
||||||
- `Organization`: Fallback type for any organization. Use this when an organization does not fit any other more specific organization type.
|
- `Organization`: Fallback type for any organization. Use this when an organization does not fit any other more specific organization type.
|
||||||
|
|
||||||
B. **Specific types (18 types, designed based on text content)**:
|
B. **Specific types (designed based on text content)**:
|
||||||
- Design more specific types for the main roles that appear in the text
|
- Design more specific types for the main roles that appear in the text
|
||||||
- Example: if the text involves an academic event, you might have `Student`, `Professor`, `University`, `ResearchGroup`, `Alumni`, etc.
|
- Example: if the text involves an academic event, you might have `Student`, `Professor`, `University`, `ResearchGroup`, `Alumni`, etc.
|
||||||
- Example: if the text involves a business event, you might have `Company`, `CEO`, `Employee`, `Investor`, `Regulator`, etc.
|
- Example: if the text involves a business event, you might have `Company`, `CEO`, `Employee`, `Investor`, `Regulator`, etc.
|
||||||
|
|
@ -120,7 +121,7 @@ B. **Specific types (18 types, designed based on text content)**:
|
||||||
|
|
||||||
### 2. Relationship Type Design
|
### 2. Relationship Type Design
|
||||||
|
|
||||||
- Quantity: 12-20
|
- Quantity: see the mandatory rules in the user message
|
||||||
- Relationships should reflect real connections in social media interactions
|
- Relationships should reflect real connections in social media interactions
|
||||||
- Ensure the source_targets in relationships cover the entity types you have defined
|
- Ensure the source_targets in relationships cover the entity types you have defined
|
||||||
- Aim for rich coverage: include hierarchical, collaborative, adversarial, and informational relationships
|
- Aim for rich coverage: include hierarchical, collaborative, adversarial, and informational relationships
|
||||||
|
|
@ -193,7 +194,7 @@ class OntologyGenerator:
|
||||||
{"role": "user", "content": user_message}
|
{"role": "user", "content": user_message}
|
||||||
]
|
]
|
||||||
|
|
||||||
# Call LLM — 20 entity types + 20 edge types need more tokens than the old 10+10
|
# Call LLM — token budget scales with ONTOLOGY_MAX_ENTITY_TYPES / ONTOLOGY_MAX_EDGE_TYPES
|
||||||
result = self.llm_client.chat_json(
|
result = self.llm_client.chat_json(
|
||||||
messages=messages,
|
messages=messages,
|
||||||
temperature=0.3,
|
temperature=0.3,
|
||||||
|
|
@ -242,16 +243,21 @@ class OntologyGenerator:
|
||||||
{additional_context}
|
{additional_context}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
max_entities = Config.ONTOLOGY_MAX_ENTITY_TYPES
|
||||||
|
max_edges = Config.ONTOLOGY_MAX_EDGE_TYPES
|
||||||
|
specific_entities = max_entities - 2
|
||||||
|
edge_min = max(1, max_edges - 2)
|
||||||
|
|
||||||
message += f"""
|
message += f"""
|
||||||
Based on the content above, design entity types and relationship types suitable for social opinion simulation.
|
Based on the content above, design entity types and relationship types suitable for social opinion simulation.
|
||||||
|
|
||||||
**Mandatory rules**:
|
**Mandatory rules**:
|
||||||
1. Output exactly 20 entity types
|
1. Output exactly {max_entities} entity types
|
||||||
2. The last 2 must be fallback types: Person (individual fallback) and Organization (organization fallback)
|
2. The last 2 must be fallback types: Person (individual fallback) and Organization (organization fallback)
|
||||||
3. The first 18 are specific types designed from the document content
|
3. The first {specific_entities} are specific types designed from the document content
|
||||||
4. All entity types must be real-world subjects capable of speaking out, not abstract concepts
|
4. All entity types must be real-world subjects capable of speaking out, not abstract concepts
|
||||||
5. Attribute names must not use reserved words: name, uuid, group_id — use full_name, org_name, etc. instead
|
5. Attribute names must not use reserved words: name, uuid, group_id — use full_name, org_name, etc. instead
|
||||||
6. Output 12-20 relationship types covering hierarchical, collaborative, adversarial, and informational relationships
|
6. Output {edge_min}-{max_edges} relationship types covering hierarchical, collaborative, adversarial, and informational relationships
|
||||||
|
|
||||||
{lang_instruction}
|
{lang_instruction}
|
||||||
"""
|
"""
|
||||||
|
|
@ -309,10 +315,8 @@ Based on the content above, design entity types and relationship types suitable
|
||||||
if len(edge.get("description", "")) > 100:
|
if len(edge.get("description", "")) > 100:
|
||||||
edge["description"] = edge["description"][:97] + "..."
|
edge["description"] = edge["description"][:97] + "..."
|
||||||
|
|
||||||
# Limits: Graphiti/Neo4j has no hard cap; Zep Cloud allows max 10 of each.
|
MAX_ENTITY_TYPES = Config.ONTOLOGY_MAX_ENTITY_TYPES
|
||||||
# We keep a generous cap for Graphiti and enforce Zep's limit at build time via config.
|
MAX_EDGE_TYPES = Config.ONTOLOGY_MAX_EDGE_TYPES
|
||||||
MAX_ENTITY_TYPES = 20
|
|
||||||
MAX_EDGE_TYPES = 20
|
|
||||||
|
|
||||||
# Deduplicate: keep first occurrence by name
|
# Deduplicate: keep first occurrence by name
|
||||||
seen_names = set()
|
seen_names = set()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue