Блог: AI-разработка
Инсайты о SaaS, технологиях, маркетинге и создании цифровых продуктов.
Публикации

В ответе ИИ три названия. Как узнать, есть ли там вы
Видимость в ответах Алисы, ChatGPT, Perplexity и нейро-блоках Яндекса можно измерить, а не угадывать. Семь показателей, правило трёх повторов и причина, по которой цифра такая.
02.10.2026
Создайте RAG-чатбот на основе контента WordPress (2026)
# Build a RAG Chatbot on WordPress Content: Complete Step-by-Step Guide ## What You'll Build A RAG (Retrieval-Augmented Generation) chatbot that: - Fetches WordPress posts via REST API - Converts posts into embeddings - Stores embeddings in Qdrant vector database - Retrieves relevant posts for user queries - Generates answers with proper citations ## Prerequisites - WordPress site with REST API enabled (WordPress 4.7+) - Python 3.10+ - Qdrant instance (local or cloud) - OpenAI API key (or alternative LLM) - Basic knowledge of Python and APIs ## Architecture Overview ``` WordPress REST API ↓ Python Script ↓ Embeddings (OpenAI) ↓ Qdrant Storage ↓ RAG Pipeline ↓ LLM Response + Citations ``` ## Step 1: Set Up Your Environment ### Install Required Dependencies ```bash pip install requests python-dotenv qdrant-client openai langchain python-dotenv ``` ### Create Environment File Create `.env`: ``` WORDPRESS_URL=https://your-wordpress-site.com WORDPRESS_USERNAME=your_username WORDPRESS_PASSWORD=your_password OPENAI_API_KEY=your_openai_key QDRANT_URL=http://localhost:6333 QDRANT_API_KEY=your_qdrant_key_or_leave_empty ``` ## Step 2: Fetch WordPress Posts via REST API ### Create WordPress Data Fetcher Create `fetch_wordpress.py`: ```python import requests import json from typing import List, Dict import os from dotenv import load_dotenv load_dotenv() class WordPressFetcher: def __init__(self, base_url: str): self.base_url = base_url.rstrip('/') self.rest_endpoint = f"{self.base_url}/wp-json/wp/v2" def fetch_all_posts(self, per_page: int = 100) -> List[Dict]: """ Fetch all posts from WordPress using pagination """ posts = [] page = 1 while True: url = f"{self.rest_endpoint}/posts" params = { 'per_page': per_page, 'page': page, 'status': 'publish' } response = requests.get(url, params=params) if response.status_code != 200: print(f"Error fetching page {page}: {response.status_code}") break page_posts = response.json() if not page_posts: break posts.extend(page_posts) page += 1 print(f"Fetched page {page - 1}, total posts: {len(posts)}") return posts def extract_post_content(self, post: Dict) -> Dict: """ Extract relevant content from WordPress post """ return { 'id': str(post['id']), 'title': post['title']['rendered'], 'content': post['content']['rendered'], 'excerpt': post['excerpt']['rendered'], 'url': post['link'], 'date': post['date'], 'author': post['author'], 'categories': post.get('categories', []) } def clean_html(self, html_content: str) -> str: """ Remove HTML tags from content """ from html.parser import HTMLParser class MLStripper(HTMLParser): def __init__(self): super().__init__() self.reset() self.strict = False self.convert_charrefs = True self.text = [] def handle_data(self, d): self.text.append(d) def get_data(self): return ''.join(self.text) stripper = MLStripper() stripper.feed(html_content) return stripper.get_data() # Usage if __name__ == "__main__": wordpress_url = os.getenv('WORDPRESS_URL') fetcher = WordPressFetcher(wordpress_url) posts = fetcher.fetch_all_posts() print(f"Total posts fetched: {len(posts)}") # Save to file for inspection with open('wordpress_posts.json', 'w') as f: json.dump([fetcher.extract_post_content(p) for p in posts], f, indent=2) ``` ### Run the Fetcher ```bash python fetch_wordpress.py ``` This creates `wordpress_posts.json` with all your posts. ## Step 3: Create Embeddings ### Set Up Embedding Generator Create `embeddings.py`: ```python from openai import OpenAI import os from dotenv import load_dotenv load_dotenv() class EmbeddingGenerator: def __init__(self, api_key: str = None): self.client = OpenAI(api_key=api_key or os.getenv('OPENAI_API_KEY')) self.model = "text-embedding-3-small" def generate_embedding(self, text: str) -> list: """ Generate embedding for a single text """ response = self.client.embeddings.create( input=text, model=self.model ) return response.data[0].embedding def generate_batch_embeddings(self, texts: list) -> list: """ Generate embeddings for multiple texts (batch is more efficient) """ response = self.client.embeddings.create( input=texts, model=self.model ) return [item.embedding for item in response.data] # Test if __name__ == "__main__": generator = EmbeddingGenerator() test_embedding = generator.generate_embedding("Test content for embedding") print(f"Embedding dimension: {len(test_embedding)}") print(f"First 5 values: {test_embedding[:5]}") ``` ## Step 4: Set Up Qdrant Vector Database ### Start Qdrant Locally (Docker) ```bash docker run -p 6333:6333 -p 6334:6334 \ -v /path/to/qdrant/storage:/qdrant/storage:z \ qdrant/qdrant:latest ``` Access Qdrant dashboard at `http://localhost:6333/dashboard` ### Create Qdrant Manager Create `qdrant_manager.py`: ```python from qdrant_client import QdrantClient from qdrant_client.models import Distance, VectorParams, PointStruct from typing import List, Dict, Tuple import os from dotenv import load_dotenv load_dotenv() class QdrantManager: def __init__(self, url: str = None, api_key: str = None): self.url = url or os.getenv('QDRANT_URL', 'http://localhost:6333') self.api_key = api_key or os.getenv('QDRANT_API_KEY') self.client = QdrantClient( url=self.url, api_key=self.api_key if self.api_key else None ) self.collection_name = "wordpress_posts" def create_collection(self, vector_size: int = 1536): """ Create collection for storing embeddings 1536 is the dimension for text-embedding-3-small """ try: self.client.recreate_collection( collection_name=self.collection_name, vectors_config=VectorParams(size=vector_size, distance=Distance.COSINE), ) print(f"Collection '{self.collection_name}' created") except Exception as e: print(f"Error creating collection: {e}") def add_posts(self, posts: List[Dict], embeddings: List[List[float]]): """ Add posts with their embeddings to Qdrant """ points = [] for idx, (post, embedding) in enumerate(zip(posts, embeddings)): point = PointStruct( id=int(post['id']), vector=embedding, payload={ 'title': post['title'], 'content': post['content'], 'excerpt': post['excerpt'], 'url': post['url'], 'date': post['date'], } ) points.append(point) self.client.upsert( collection_name=self.collection_name, points=points, ) print(f"Added {len(points)} posts to Qdrant") def search(self, query_embedding: List[float], limit: int = 5) -> List[Dict]: """ Search for similar posts """ results = self.client.search( collection_name=self.collection_name, query_vector=query_embedding, limit=limit, ) retrieved_posts = [] for result in results: retrieved_posts.append({ 'id': result.id, 'score': result.score, 'title': result.payload['title'], 'content': result.payload['content'], 'url': result.payload['url'], 'date': result.payload['date'], }) return retrieved_posts def get_collection_info(self): """ Get collection statistics """ info = self.client.get_collection(self.collection_name) return info # Test if __name__ == "__main__": manager = QdrantManager() info = manager.get_collection_info() print(f"Collection info: {info}") ``` ## Step 5: Index WordPress Posts into Qdrant ### Create Indexing Script Create `index_posts.py`: ```python import json from fetch_wordpress import WordPressFetcher from embeddings import EmbeddingGenerator from qdrant_manager import QdrantManager import os from dotenv import load_dotenv from html.parser import HTMLParser load_dotenv() class HTMLStripper(HTMLParser): def __init__(self): super().__init__() self.reset() self.strict = False self.convert_charrefs = True self.text = [] def handle_data(self, d): self.text.append(d) def get_data(self): return ''.join(self.text) def strip_html(html): stripper = HTMLStripper() stripper.feed(html) return stripper.get_data() def index_wordpress_posts(): """ Main indexing pipeline """ print("Step 1: Fetching WordPress posts...") wordpress_url = os.getenv('WORDPRESS_URL') fetcher = WordPressFetcher(wordpress_url) raw_posts = fetcher.fetch_all_posts() # Extract and clean content posts = [] for raw_post in raw_posts: post = fetcher.extract_post_content(raw_post) post['content'] = strip_html(post['content']) post['excerpt'] = strip_html(post['excerpt']) posts.append(post) print(f"Extracted {len(posts)} posts") print("\nStep 2: Generating embeddings...") generator = EmbeddingGenerator() # Combine title and content for embedding texts_to_embed = [ f"{post['title']}\n{post['content'][:500]}" # Use first 500 chars for post in posts ] embeddings = generator.generate_batch_embeddings(texts_to_embed) print(f"Generated {len(embeddings)} embeddings") print("\nStep 3: Indexing into Qdrant...") manager = QdrantManager() manager.create_collection(vector_size=1536) manager.add_posts(posts, embeddings) print("\nStep 4: Verifying...") info = manager.get_collection_info() print(f"Collection has {info.points_count} points") print("✓ Indexing complete!") if __name__ == "__main__": index_wordpress_posts() ``` ### Run the Indexer ```bash python index_posts.py ``` This will: - Fetch all posts - Generate embeddings - Store in Qdrant - Display progress ## Step 6: Build the RAG Chatbot ### Create RAG Pipeline Create `rag_chatbot.py`: ```python from embeddings import EmbeddingGenerator from qdrant_manager import QdrantManager from openai import OpenAI from typing import List, Dict, Tuple import os from dotenv import load_dotenv load_dotenv() class RAGChatbot: def __init__(self): self.embedding_generator = EmbeddingGenerator() self.qdrant_manager = QdrantManager() self.llm_client = OpenAI(api_key=os.getenv('OPENAI_API_KEY')) self.model = "gpt-4o-mini" def retrieve_relevant_posts(self, query: str, top_k: int = 5) -> List[Dict]: """ Retrieve relevant posts for a query """ # Generate embedding for the query query_embedding = self.embedding_generator.generate_embedding(query) # Search in Qdrant results = self.qdrant_manager.search(query_embedding, limit=top_k) return results def generate_answer_with_citations( self, query: str, retrieved_posts: List[Dict] ) -> Tuple[str, List[Dict]]: """ Generate answer using LLM with citations """ # Format context from retrieved posts context = self._format_context(retrieved_posts) # Create prompt system_prompt = """You are a helpful assistant answering questions about WordPress blog posts. Use the provided post content to answer questions accurately. Always cite the source posts by title and URL in your response. If you can't find relevant information, say so explicitly.""" user_prompt = f"""Based on the following posts, answer the question: "{query}" POSTS: {context} Please provide a comprehensive answer with citations to the source posts.""" # Call LLM response = self.llm_client.chat.completions.create( model=self.model, messages=[ {"role": "system", "content": system_prompt}, {"role": "user", "content": user_prompt} ], temperature=0.7, max_tokens=1000 ) answer = response.choices[0].message.content return answer, retrieved_posts def _format_context(self, posts: List[Dict]) -> str: """ Format retrieved posts into a context string """ context_parts = [] for i, post in enumerate(posts, 1): context_parts.append(f""" Post {i}: {post['title']} URL: {post['url']} Relevance Score: {post['score']:.3f} Content: {post['content'][:800]}... ---""") return "\n".join(context_parts) def chat(self, query: str, top_k: int = 5) ->
26.06.2026WordPress как бэкенд для RAG: Как мы это сделали и почему это работает
Как мы сделали из WordPress базу знаний для ИИ-ассистента: публичные и приватные страницы, вебхук, Qdrant и гибридный поиск. Что сработало на практике.
02.05.2026
EasyTalk: как я создал плагин для WordPress, чтобы превращать статьи в аудио с помощью ElevenLabs
Кратко: Я хотел, чтобы мои блог-посты можно было не только читать, но и слушать. Я создал плагин для WordPress, который преобразует посты в естественно звучащее аудио с использованием API ElevenLabs. Он работает с многоязычными сайтами и позволяет посетителям прослушивать посты одним нажатием. Проблема: Люди не всегда…
10.02.2026
Как я создал плагин для WordPress для генерации изображений с использованием ИИ за один вечер с помощью ИИ Claude Code 8-)
TL;DR: Уставший тратить время на поиск иллюстраций для блог-постов. Создал плагин, который генерирует изображения для обложек с одним нажатием внутри WordPress. Freepik дает вам $5 кредита при регистрации — достаточно для 100-250 бесплатных изображений. Проблема: Иллюстрации съедают ваше время Каждый, кто ведет блог,…
04.02.2026