feat(chat): Add post-processing for automatic markdown links
- Call _postprocess_links() on AI response before returning - Ensures companies and people are linked even when AI doesn't format them - Fixes inconsistent link generation by Gemini AI Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
827a4df1e2
commit
05d8e3f6ec
@ -1132,11 +1132,74 @@ BŁĘDNIE (NIE RÓB - resetuje numerację):
|
||||
user_id=user_id,
|
||||
temperature=0.7
|
||||
)
|
||||
return response_text
|
||||
# Post-process to ensure links are added even if AI didn't format them
|
||||
return self._postprocess_links(response_text, context)
|
||||
else:
|
||||
# Legacy: direct API call (no centralized cost tracking)
|
||||
response = self.model.generate_content(full_prompt)
|
||||
return response.text
|
||||
# Post-process to ensure links are added even if AI didn't format them
|
||||
return self._postprocess_links(response.text, context)
|
||||
|
||||
def _postprocess_links(self, text: str, context: Dict) -> str:
|
||||
"""
|
||||
Post-process AI response to add markdown links for companies and people.
|
||||
This ensures consistent linking regardless of AI behavior.
|
||||
|
||||
Args:
|
||||
text: AI response text
|
||||
context: Context dict with company_people data
|
||||
|
||||
Returns:
|
||||
Text with names replaced by markdown links
|
||||
"""
|
||||
import re
|
||||
|
||||
# Build lookup dict: name -> url
|
||||
name_to_url = {}
|
||||
|
||||
# Extract companies and people from company_people context
|
||||
company_people = context.get('company_people', {})
|
||||
for company_name, data in company_people.items():
|
||||
# Add company
|
||||
if data.get('profile'):
|
||||
name_to_url[company_name] = data['profile']
|
||||
# Add people
|
||||
for person in data.get('people', []):
|
||||
if person.get('name') and person.get('profile'):
|
||||
name_to_url[person['name']] = person['profile']
|
||||
|
||||
# Also extract from companies list (context['companies'] has profile URLs)
|
||||
# Companies format: list of dicts with 'name' and 'profile'
|
||||
# This is populated by _company_to_compact_dict
|
||||
|
||||
# Sort by name length (longest first) to avoid partial replacements
|
||||
sorted_names = sorted(name_to_url.keys(), key=len, reverse=True)
|
||||
|
||||
for name in sorted_names:
|
||||
url = name_to_url[name]
|
||||
if not name or not url:
|
||||
continue
|
||||
|
||||
# Skip if already a markdown link
|
||||
# Pattern: [Name](url) - already linked
|
||||
already_linked = re.search(r'\[' + re.escape(name) + r'\]\([^)]+\)', text)
|
||||
if already_linked:
|
||||
continue
|
||||
|
||||
# Replace **Name** (bold) with [Name](url)
|
||||
bold_pattern = r'\*\*' + re.escape(name) + r'\*\*'
|
||||
if re.search(bold_pattern, text):
|
||||
text = re.sub(bold_pattern, f'[{name}]({url})', text, count=1)
|
||||
continue
|
||||
|
||||
# Replace plain "Name" at word boundaries (but not if already in link)
|
||||
# Be careful not to replace inside existing markdown
|
||||
plain_pattern = r'(?<!\[)(?<!\()' + re.escape(name) + r'(?!\])(?!\))'
|
||||
if re.search(plain_pattern, text):
|
||||
# Only replace first occurrence to avoid over-linking
|
||||
text = re.sub(plain_pattern, f'[{name}]({url})', text, count=1)
|
||||
|
||||
return text
|
||||
|
||||
def _calculate_cost(self, input_tokens: int, output_tokens: int) -> float:
|
||||
"""
|
||||
|
||||
Loading…
Reference in New Issue
Block a user