File size: 26,498 Bytes
4a25546
2e6803f
 
4a25546
 
 
 
 
364049b
2e6803f
4a25546
 
 
2e6803f
1169bfe
2e6803f
4a25546
2e6803f
4a25546
2e6803f
1169bfe
2e6803f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ac748c8
2e6803f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ac748c8
2e6803f
8662a42
2e6803f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
faea0d1
2e6803f
 
364049b
2e6803f
 
 
 
 
 
 
 
 
364049b
 
2e6803f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
364049b
2e6803f
 
364049b
2e6803f
364049b
 
2e6803f
faea0d1
2e6803f
 
364049b
 
2e6803f
 
364049b
 
 
2e6803f
 
 
 
364049b
 
 
 
2e6803f
364049b
2e6803f
 
364049b
2e6803f
 
364049b
 
 
 
 
2e6803f
 
 
 
364049b
 
2e6803f
 
364049b
 
 
2e6803f
 
 
 
364049b
 
 
 
 
2e6803f
 
364049b
 
 
 
 
 
2e6803f
4a25546
2e6803f
364049b
2e6803f
364049b
 
2e6803f
 
364049b
 
2e6803f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
364049b
 
2e6803f
364049b
 
 
 
 
2e6803f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
364049b
 
2e6803f
364049b
 
 
2e6803f
 
 
 
 
364049b
2e6803f
 
 
 
 
 
364049b
2e6803f
 
 
 
 
 
364049b
 
 
 
2e6803f
4a25546
2e6803f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4a25546
2e6803f
364049b
2e6803f
 
 
364049b
2e6803f
 
 
 
 
 
 
 
 
 
364049b
2e6803f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4a25546
2e6803f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ac748c8
2e6803f
 
ac748c8
2e6803f
 
 
 
 
 
 
364049b
2e6803f
 
364049b
2e6803f
 
364049b
2e6803f
 
364049b
2e6803f
 
364049b
2e6803f
 
 
 
 
364049b
 
 
 
 
 
 
 
 
 
 
 
2e6803f
364049b
 
 
2e6803f
 
 
 
 
 
 
 
364049b
 
 
 
 
 
2e6803f
 
 
 
 
 
 
 
364049b
 
 
 
 
2e6803f
 
 
 
 
 
 
 
364049b
2e6803f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
"""
Enhanced Content Optimization Module with RAG for GEO
Integrates RAG functionality for better Generative Engine Optimization
"""

import json
import re
from typing import Dict, Any, List, Optional
from langchain.prompts import ChatPromptTemplate, SystemMessagePromptTemplate, HumanMessagePromptTemplate
from langchain.schema import Document


class ContentOptimizer:
    """Enhanced Content Optimizer with RAG capabilities for GEO"""

    def __init__(self, llm, vector_chunker=None):
        self.llm = llm
        self.vector_chunker = vector_chunker
        self.setup_prompts()
        self.setup_geo_knowledge_base()

    def setup_geo_knowledge_base(self):
        """Initialize GEO best practices knowledge base"""
        self.geo_knowledge = [
            """
            Generative Engine Optimization (GEO) Best Practices:
            
            1. Structure for AI Consumption:
            - Use clear headings and subheadings
            - Include bullet points and numbered lists
            - Provide direct, concise answers to common questions
            - Use schema markup when possible
            
            2. Content Format for LLMs:
            - Answer questions directly in the first sentence
            - Use "what, why, how" question patterns
            - Include relevant entities and proper nouns
            - Maintain factual accuracy with citations
            
            3. Semantic Optimization:
            - Include related terms and synonyms
            - Use entity-rich content (people, places, organizations)
            - Connect concepts with clear relationships
            - Optimize for topic clusters, not just keywords
            """,
            
            """
            AI Search Visibility Optimization:
            
            1. Query Intent Matching:
            - Address user intent explicitly
            - Use natural language patterns
            - Include question-answer pairs
            - Optimize for conversational queries
            
            2. Citation Worthiness:
            - Include authoritative sources and data
            - Use specific facts and statistics
            - Provide expert opinions and insights
            - Maintain consistent tone and expertise
            
            3. Multi-Query Coverage:
            - Address related questions in the same content
            - Use comprehensive topic coverage
            - Include long-tail and specific queries
            - Provide context for complex topics
            """,
            
            """
            Content Structure for AI Systems:
            
            1. Information Architecture:
            - Lead with key information
            - Use inverted pyramid structure
            - Include table of contents for long content
            - Break complex topics into digestible sections
            
            2. Conversational Readiness:
            - Write in active voice
            - Use clear, direct language
            - Include transitional phrases
            - Optimize sentence length (12-20 words)
            
            3. Context Completeness:
            - Define technical terms
            - Provide background information
            - Include relevant examples
            - Connect to broader topic context
            """
        ]

    def setup_prompts(self):
        """Initialize optimization prompts with RAG integration"""
        
        self.rag_enhancement_prompt = """
        You are a Generative Engine Optimization (GEO) specialist with access to best practices knowledge.
        
        Based on the provided GEO knowledge and the user's content, optimize the content for:
        1. AI search engines (ChatGPT, Claude, Gemini)
        2. LLM-based question answering systems
        3. Conversational AI interfaces
        4. Citation and reference systems
        
        Use the knowledge base to inform your optimization decisions.
        
        Knowledge Base Context:
        {context}
        
        Original Content:
        {content}
        
        Provide comprehensive GEO optimization in JSON format:
        ```json
        {{
          "geo_analysis": {{
            "current_geo_score": 7.5,
            "ai_search_visibility": 8.0,
            "query_intent_matching": 7.0,
            "conversational_readiness": 8.5,
            "citation_worthiness": 6.5,
            "context_completeness": 7.5
          }},
          "optimization_opportunities": [
            {{
              "type": "Structure Enhancement",
              "description": "Add clear headings and Q&A format",
              "priority": "high",
              "expected_impact": "Improve AI parsing by 25%"
            }}
          ],
          "optimized_content": {{
            "enhanced_text": "Your optimized content here...",
            "structural_improvements": ["Added FAQ section", "Improved headings"],
            "semantic_enhancements": ["Added related terms", "Improved entity density"]
          }},
          "geo_keywords": {{
            "primary_entities": ["entity1", "entity2"],
            "semantic_terms": ["term1", "term2"],
            "question_patterns": ["What is...", "How does..."],
            "related_concepts": ["concept1", "concept2"]
          }},
          "recommendations": [
            "Add more specific examples",
            "Include authoritative citations",
            "Improve conversational flow"
          ]
        }}
        ```
        """
        
        self.competitive_geo_prompt = """
        Analyze the content against GEO best practices and identify competitive optimization opportunities.
        
        GEO Knowledge Base:
        {context}
        
        Content to Analyze:
        {content}
        
        Provide competitive GEO analysis:
        ```json
        {{
          "competitive_gaps": {{
            "missing_question_patterns": ["What questions aren't covered"],
            "entity_gaps": ["Important entities not mentioned"],
            "semantic_opportunities": ["Related terms to include"],
            "structural_weaknesses": ["Formatting issues for AI"]
          }},
          "benchmark_comparison": {{
            "current_performance": {{
              "ai_answerability": 6.5,
              "semantic_richness": 7.0,
              "structural_clarity": 8.0
            }},
            "optimization_potential": {{
              "ai_answerability": 9.0,
              "semantic_richness": 8.5,
              "structural_clarity": 9.5
            }}
          }},
          "action_plan": [
            {{
              "priority": "high",
              "action": "Add FAQ section",
              "rationale": "Improves direct question answering"
            }}
          ]
        }}
        ```
        """

    def optimize_content_with_rag(self, content: str, optimization_type: str = "geo_standard", 
                                 analyze_only: bool = False) -> Dict[str, Any]:
        """
        Main RAG-enhanced content optimization for GEO
        
        Args:
            content (str): Content to optimize
            optimization_type (str): Type of GEO optimization
            analyze_only (bool): Whether to only analyze without rewriting
            
        Returns:
            Dict: Comprehensive GEO optimization results
        """
        try:
            # Create knowledge base documents
            knowledge_docs = [Document(page_content=knowledge, metadata={"source": "geo_best_practices"}) 
                            for knowledge in self.geo_knowledge]
            
            if self.vector_chunker:
                # Use RAG to get relevant knowledge
                qa_chain = self.vector_chunker.create_qa_chain(knowledge_docs, self.llm)
                
                # Query for relevant GEO practices
                geo_query = f"How to optimize this type of content for AI search engines: {content[:500]}"
                context_result = qa_chain({"query": geo_query})
                context = context_result.get("result", "")
            else:
                # Fallback to using all knowledge if vector_chunker not available
                context = "\n\n".join(self.geo_knowledge)
            
            # Choose optimization approach
            if optimization_type == "competitive_geo":
                return self._competitive_geo_optimization(content, context)
            else:
                return self._standard_geo_optimization(content, context, analyze_only)
                
        except Exception as e:
            return {'error': f"RAG-enhanced optimization failed: {str(e)}"}

    def _standard_geo_optimization(self, content: str, context: str, analyze_only: bool) -> Dict[str, Any]:
        """Standard GEO optimization with RAG context"""
        try:
            prompt_template = ChatPromptTemplate.from_messages([
                SystemMessagePromptTemplate.from_template(self.rag_enhancement_prompt),
                HumanMessagePromptTemplate.from_template("Optimize this content using GEO best practices.")
            ])
            
            chain = prompt_template | self.llm
            result = chain.invoke({
                "context": context,
                "content": content[:5000]  # Limit content length
            })
            
            result_content = result.content if hasattr(result, 'content') else str(result)
            parsed_result = self._parse_optimization_result(result_content)
            
            # Add metadata
            parsed_result.update({
                'optimization_type': 'geo_standard',
                'rag_enhanced': True,
                'analyze_only': analyze_only,
                'original_length': len(content),
                'knowledge_sources': len(self.geo_knowledge)
            })
            
            return parsed_result
            
        except Exception as e:
            return {'error': f"Standard GEO optimization failed: {str(e)}"}

    def _competitive_geo_optimization(self, content: str, context: str) -> Dict[str, Any]:
        """Competitive GEO analysis with RAG context"""
        try:
            prompt_template = ChatPromptTemplate.from_messages([
                SystemMessagePromptTemplate.from_template(self.competitive_geo_prompt),
                HumanMessagePromptTemplate.from_template("Perform competitive GEO analysis.")
            ])
            
            chain = prompt_template | self.llm
            result = chain.invoke({
                "context": context,
                "content": content[:5000]
            })
            
            result_content = result.content if hasattr(result, 'content') else str(result)
            parsed_result = self._parse_optimization_result(result_content)
            
            parsed_result.update({
                'optimization_type': 'competitive_geo',
                'rag_enhanced': True,
                'competitive_analysis': True
            })
            
            return parsed_result
            
        except Exception as e:
            return {'error': f"Competitive GEO optimization failed: {str(e)}"}

    def batch_optimize_with_rag(self, content_list: List[str], optimization_type: str = "geo_standard") -> List[Dict[str, Any]]:
        """
        Batch optimize multiple content pieces with RAG
        
        Args:
            content_list: List of content to optimize
            optimization_type: Type of optimization
            
        Returns:
            List of optimization results
        """
        results = []
        
        for i, content in enumerate(content_list):
            try:
                result = self.optimize_content_with_rag(
                    content, 
                    optimization_type=optimization_type
                )
                result['batch_index'] = i
                results.append(result)
                
            except Exception as e:
                results.append({
                    'batch_index': i,
                    'error': f"Batch GEO optimization failed: {str(e)}"
                })
        
        return results

    def analyze_geo_readability(self, content: str) -> Dict[str, Any]:
        """
        Analyze content readability specifically for GEO/AI systems
        """
        try:
            # Basic metrics
            words = content.split()
            sentences = re.split(r'[.!?]+', content)
            sentences = [s.strip() for s in sentences if s.strip()]
            paragraphs = [p.strip() for p in content.split('\n\n') if p.strip()]
            
            # GEO-specific analysis
            questions = len(re.findall(r'\?', content))
            headings = len(re.findall(r'^#+\s', content, re.MULTILINE))
            lists = len(re.findall(r'^\s*[-*+]\s', content, re.MULTILINE))
            numbers = len(re.findall(r'\b\d+\.?\d*\b', content))
            
            # Entity-like patterns (proper nouns)
            entities = len(re.findall(r'\b[A-Z][a-z]+(?:\s+[A-Z][a-z]+)*\b', content))
            
            # Calculate GEO readability score
            geo_score = self._calculate_geo_readability_score({
                'avg_words_per_sentence': len(words) / len(sentences) if sentences else 0,
                'questions_ratio': questions / len(sentences) if sentences else 0,
                'structure_elements': headings + lists,
                'entity_density': entities / len(words) if words else 0,
                'numeric_data': numbers / len(words) if words else 0
            })
            
            return {
                'geo_readability_metrics': {
                    'total_words': len(words),
                    'total_sentences': len(sentences),
                    'total_paragraphs': len(paragraphs),
                    'questions_count': questions,
                    'headings_count': headings,
                    'lists_count': lists,
                    'entity_mentions': entities,
                    'numeric_data_points': numbers
                },
                'geo_readability_score': geo_score,
                'ai_optimization_indicators': {
                    'question_ratio': questions / len(sentences) if sentences else 0,
                    'structure_score': min(10, (headings + lists) * 2),
                    'entity_density': entities / len(words) if words else 0,
                    'data_richness': numbers / len(words) if words else 0
                },
                'geo_recommendations': self._generate_geo_recommendations({
                    'questions': questions,
                    'headings': headings,
                    'lists': lists,
                    'entities': entities,
                    'sentences': len(sentences)
                })
            }
            
        except Exception as e:
            return {'error': f"GEO readability analysis failed: {str(e)}"}

    def extract_geo_entities(self, content: str) -> Dict[str, Any]:
        """
        Extract entities and concepts relevant for GEO optimization
        """
        try:
            if not self.vector_chunker:
                return {'error': 'Vector chunker not available for entity extraction'}
            
            # Create knowledge context about entity extraction
            entity_knowledge = [Document(
                page_content="""
                For GEO optimization, important entities include:
                1. Named entities: People, organizations, locations, brands
                2. Technical concepts: Industry terms, methodologies, tools
                3. Topical entities: Core subjects, themes, categories
                4. Relational entities: Connected concepts, dependencies
                5. Question entities: What users commonly ask about
                """,
                metadata={"source": "entity_extraction_guide"}
            )]
            
            qa_chain = self.vector_chunker.create_qa_chain(entity_knowledge, self.llm)
            
            # Extract different types of entities
            extraction_queries = [
                "What are the main named entities (people, places, organizations) in this content?",
                "What are the key technical concepts and terms?",
                "What questions might users have about this content?",
                "What related topics and concepts are mentioned?"
            ]
            
            extracted_data = {}
            for query in extraction_queries:
                full_query = f"{query}\n\nContent: {content[:3000]}"
                result = qa_chain({"query": full_query})
                query_key = query.split('?')[0].lower().replace(' ', '_').replace('what_are_the_', '')
                extracted_data[query_key] = result.get("result", "")
            
            return {
                'geo_entities': extracted_data,
                'extraction_method': 'rag_enhanced',
                'content_length': len(content),
                'extraction_success': True
            }
            
        except Exception as e:
            return {'error': f"GEO entity extraction failed: {str(e)}"}

    def generate_geo_variations(self, content: str, num_variations: int = 3) -> List[Dict[str, Any]]:
        """
        Generate GEO-optimized content variations using RAG
        """
        variations = []
        
        variation_types = [
            ("faq_focused", "Transform into FAQ format optimized for AI Q&A systems"),
            ("conversational", "Optimize for conversational AI and voice search"),
            ("authoritative", "Enhance with authoritative tone for citation systems")
        ]
        
        try:
            # Get GEO context
            knowledge_docs = [Document(page_content=knowledge, metadata={"source": "geo_practices"}) 
                            for knowledge in self.geo_knowledge]
            
            if self.vector_chunker:
                qa_chain = self.vector_chunker.create_qa_chain(knowledge_docs, self.llm)
                
                for i, (variation_type, description) in enumerate(variation_types[:num_variations]):
                    try:
                        # Get specific guidance for this variation type
                        context_query = f"How to optimize content for {variation_type} in AI systems?"
                        context_result = qa_chain({"query": context_query})
                        context = context_result.get("result", "")
                        
                        variation_prompt = f"""
                        Create a {variation_type} version of the content optimized for GEO.
                        
                        Context: {context}
                        
                        Original Content: {content[:4000]}
                        
                        Variation Goal: {description}
                        
                        Return JSON:
                        {{
                          "variation_type": "{variation_type}",
                          "optimized_content": "the rewritten content...",
                          "geo_improvements": ["improvement 1", "improvement 2"],
                          "target_ai_systems": ["ChatGPT", "Claude", "etc"],
                          "expected_geo_benefits": ["benefit 1", "benefit 2"]
                        }}
                        """
                        
                        prompt_template = ChatPromptTemplate.from_messages([
                            SystemMessagePromptTemplate.from_template(variation_prompt),
                            HumanMessagePromptTemplate.from_template("Generate the GEO-optimized variation.")
                        ])
                        
                        chain = prompt_template | self.llm
                        result = chain.invoke({})
                        
                        result_content = result.content if hasattr(result, 'content') else str(result)
                        parsed_result = self._parse_optimization_result(result_content)
                        
                        parsed_result.update({
                            'variation_index': i,
                            'rag_enhanced': True,
                            'geo_optimized': True
                        })
                        
                        variations.append(parsed_result)
                        
                    except Exception as e:
                        variations.append({
                            'variation_index': i,
                            'variation_type': variation_type,
                            'error': f"GEO variation generation failed: {str(e)}"
                        })
            else:
                return [{'error': 'Vector chunker not available for variation generation'}]
        
        except Exception as e:
            return [{'error': f"GEO variation generation failed: {str(e)}"}]
        
        return variations

    def _calculate_geo_readability_score(self, metrics: Dict[str, float]) -> float:
        """Calculate GEO-specific readability score"""
        try:
            # GEO-optimized scoring
            sentence_score = max(0, 10 - abs(metrics['avg_words_per_sentence'] - 15) * 0.3)
            question_score = min(10, metrics['questions_ratio'] * 50)  # Reward questions
            structure_score = min(10, metrics['structure_elements'] * 1.5)  # Reward headings/lists
            entity_score = min(10, metrics['entity_density'] * 100)  # Reward entities
            data_score = min(10, metrics['numeric_data'] * 200)  # Reward data points
            
            # Weighted for GEO priorities
            overall_score = (
                sentence_score * 0.2 + 
                question_score * 0.25 + 
                structure_score * 0.25 + 
                entity_score * 0.15 + 
                data_score * 0.15
            )
            
            return round(overall_score, 1)
            
        except Exception:
            return 5.0

    def _generate_geo_recommendations(self, metrics: Dict[str, int]) -> List[str]:
        """Generate GEO-specific recommendations"""
        recommendations = []
        
        try:
            if metrics['questions'] == 0:
                recommendations.append("Add FAQ section or question-based headings for better AI Q&A performance")
            
            if metrics['headings'] < 2:
                recommendations.append("Add more structured headings to improve AI content parsing")
            
            if metrics['lists'] == 0:
                recommendations.append("Include bullet points or numbered lists for better information extraction")
            
            if metrics['entities'] < 5:
                recommendations.append("Include more specific entities (names, places, organizations) for authority")
            
            if metrics['questions'] / metrics['sentences'] < 0.1:
                recommendations.append("Consider transforming statements into question-answer pairs")
            
            return recommendations
            
        except Exception:
            return ["Unable to generate specific GEO recommendations"]

    def _parse_optimization_result(self, response_text: str) -> Dict[str, Any]:
        """Parse LLM response and extract structured results"""
        try:
            # Find JSON content in the response
            json_start = response_text.find('{')
            json_end = response_text.rfind('}') + 1
            
            if json_start != -1 and json_end != -1:
                json_str = response_text[json_start:json_end]
                parsed = json.loads(json_str)
                return parsed
            else:
                # If no JSON found, return structured error
                return {
                    'raw_response': response_text,
                    'parsing_error': 'No JSON structure found in response',
                    'geo_analysis': {
                        'current_geo_score': 0,
                        'ai_search_visibility': 0,
                        'query_intent_matching': 0,
                        'conversational_readiness': 0,
                        'citation_worthiness': 0,
                        'context_completeness': 0
                    }
                }
                
        except json.JSONDecodeError as e:
            return {
                'raw_response': response_text,
                'parsing_error': f'JSON decode error: {str(e)}',
                'geo_analysis': {
                    'current_geo_score': 0,
                    'ai_search_visibility': 0,
                    'query_intent_matching': 0,
                    'conversational_readiness': 0,
                    'citation_worthiness': 0,
                    'context_completeness': 0
                }
            }
        except Exception as e:
            return {
                'raw_response': response_text,
                'parsing_error': f'Unexpected parsing error: {str(e)}',
                'geo_analysis': {
                    'current_geo_score': 0,
                    'ai_search_visibility': 0,
                    'query_intent_matching': 0,
                    'conversational_readiness': 0,
                    'citation_worthiness': 0,
                    'context_completeness': 0
                }
            }

    # Legacy methods for backward compatibility
    def optimize_content(self, content: str, analyze_only: bool = False, 
                        include_keywords: bool = True, optimization_type: str = "standard") -> Dict[str, Any]:
        """
        Legacy method - redirects to RAG-enhanced optimization
        """
        if optimization_type == "standard":
            return self.optimize_content_with_rag(content, "geo_standard", analyze_only)
        elif optimization_type == "seo":
            return self.optimize_content_with_rag(content, "geo_standard", analyze_only)
        elif optimization_type == "competitive":
            return self.optimize_content_with_rag(content, "competitive_geo", analyze_only)
        else:
            return self.optimize_content_with_rag(content, "geo_standard", analyze_only)

    def analyze_content_readability(self, content: str) -> Dict[str, Any]:
        """Legacy method - redirects to GEO readability analysis"""
        return self.analyze_geo_readability(content)