Интеграция Firecrawl с LangChain для создания RAG систем и AI агентов
pip install langchain langchain-openai chromadb requests
from langchain.document_loaders.base import BaseLoader
from langchain.docstore.document import Document
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.vectorstores import Chroma
from langchain.embeddings import OpenAIEmbeddings
from langchain.llms import OpenAI
from langchain.chains import RetrievalQA
import requests
class FirecrawlLoader(BaseLoader):
"""Custom LangChain loader for Firecrawl API"""
def __init__(self, api_key: str, urls: list = None, search_query: str = None):
self.api_key = api_key
self.urls = urls or []
self.search_query = search_query
self.base_url = "https://api.firecrawl.ru/v1"
self.headers = {"X-API-Key": api_key}
def load(self) -> list[Document]:
"""Load documents from Firecrawl API"""
documents = []
# Если есть URLs - парсим их
if self.urls:
for url in self.urls:
doc = self._scrape_url(url)
if doc:
documents.append(doc)
# Если есть поисковый запрос - ищем контент
if self.search_query:
search_docs = self._search_content(self.search_query)
documents.extend(search_docs)
return documents
def _scrape_url(self, url: str) -> Document:
"""Scrape single URL"""
response = requests.post(f"{self.base_url}/scrape",
headers=self.headers,
json={
"url": url,
"formats": ["markdown"],
"onlyMainContent": True
}
)
data = response.json()
if data.get('success'):
metadata = {
'source': url,
'title': data['data'].get('metadata', {}).get('title', ''),
'scraped_at': data.get('processingTime', 0)
}
return Document(
page_content=data['data']['markdown'],
metadata=metadata
)
return None
def _search_content(self, query: str) -> list[Document]:
"""Search content and return documents"""
response = requests.post(f"{self.base_url}/search",
headers=self.headers,
json={
"query": query,
"limit": 10,
"parseResults": False
}
)
data = response.json()
documents = []
if data.get('success') and data['data']['pages']:
for page in data['data']['pages']:
# Дополнительно парсим каждую найденную страницу
doc = self._scrape_url(page['url'])
if doc:
# Добавляем метаданные поиска
doc.metadata.update({
'search_query': query,
'search_title': page['title'],
'search_description': page['description']
})
documents.append(doc)
return documents
# Создание RAG системы
def create_rag_system(firecrawl_api_key: str, openai_api_key: str):
# 1. Загрузка документов через Firecrawl
loader = FirecrawlLoader(
api_key=firecrawl_api_key,
search_query="машинное обучение тренды 2025"
)
documents = loader.load()
# 2. Разбиение на чанки
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=200
)
splits = text_splitter.split_documents(documents)
# 3. Создание векторного хранилища
embeddings = OpenAIEmbeddings(openai_api_key=openai_api_key)
vectorstore = Chroma.from_documents(splits, embeddings)
# 4. Создание QA цепочки
llm = OpenAI(openai_api_key=openai_api_key, temperature=0)
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff",
retriever=vectorstore.as_retriever(search_kwargs={"k": 3}),
return_source_documents=True
)
return qa_chain
# Использование RAG системы
rag_system = create_rag_system(
firecrawl_api_key="your_firecrawl_key",
openai_api_key="your_openai_key"
)
# Задаем вопросы на основе актуальных данных
result = rag_system({
"query": "Какие основные тренды в машинном обучении на 2025 год?"
})
print("Ответ:", result['result'])
print("\nИсточники:")
for doc in result['source_documents']:
print(f"- {doc.metadata['source']}")
from langchain.agents import Tool, AgentExecutor, create_react_agent
from langchain.prompts import PromptTemplate
from langchain.llms import OpenAI
class FirecrawlTools:
"""Набор инструментов для AI агентов"""
def __init__(self, api_key: str):
self.api_key = api_key
self.headers = {"X-API-Key": api_key}
self.base_url = "https://api.firecrawl.ru/v1"
def search_web(self, query: str) -> str:
"""Поиск информации в интернете"""
response = requests.post(f"{self.base_url}/search",
headers=self.headers,
json={
"query": query,
"limit": 5,
"parseResults": True,
"aiPrompt": f"Кратко суммируй ключевую информацию по запросу: {query}"
}
)
data = response.json()
if data.get('success'):
if 'markdown' in data['data']:
return data['data']['markdown']
else:
# Если нет AI анализа, возвращаем список страниц
pages = data['data']['pages'][:3]
result = f"Найдено по запросу '{query}':\n\n"
for i, page in enumerate(pages, 1):
result += f"{i}. {page['title']}\n{page['url']}\n{page['description']}\n\n"
return result
return f"Не удалось найти информацию по запросу: {query}"
def scrape_url(self, url: str) -> str:
"""Парсинг конкретного URL"""
response = requests.post(f"{self.base_url}/scrape",
headers=self.headers,
json={
"url": url,
"formats": ["markdown"],
"onlyMainContent": True
}
)
data = response.json()
if data.get('success'):
content = data['data']['markdown']
# Ограничиваем длину для агента
return content[:2000] + "..." if len(content) > 2000 else content
return f"Не удалось получить контент с {url}"
def analyze_competitor(self, company_name: str) -> str:
"""Анализ конкурента"""
query = f"{company_name} компания услуги продукты"
return self.search_web(query)
# Создание инструментов для агента
def create_firecrawl_agent(firecrawl_api_key: str, openai_api_key: str):
tools_helper = FirecrawlTools(firecrawl_api_key)
tools = [
Tool(
name="search_web",
description="Поиск актуальной информации в интернете. Используй для поиска новостей, трендов, статистики.",
func=tools_helper.search_web
),
Tool(
name="scrape_url",
description="Получение контента с конкретного URL. Используй когда нужен контент с определенной страницы.",
func=tools_helper.scrape_url
),
Tool(
name="analyze_competitor",
description="Анализ конкурента по названию компании. Возвращает информацию о продуктах и услугах.",
func=tools_helper.analyze_competitor
)
]
# Промпт для агента
template = """
Ты AI-помощник с доступом к актуальным веб-данным через Firecrawl API.
Доступные инструменты:
{tools}
Инструкции:
1. Используй search_web для поиска актуальной информации
2. Используй scrape_url для получения контента с конкретных URL
3. Используй analyze_competitor для анализа компаний
4. Всегда указывай источники информации
5. Если информация устарела, ищи более свежие данные
Вопрос: {input}
Мысли: {agent_scratchpad}
"""
prompt = PromptTemplate.from_template(template)
llm = OpenAI(openai_api_key=openai_api_key, temperature=0)
agent = create_react_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
return agent_executor
# Использование агента
agent = create_firecrawl_agent(
firecrawl_api_key="your_firecrawl_key",
openai_api_key="your_openai_key"
)
# Примеры запросов
responses = agent.run("Какие новые тренды в веб-разработке появились в 2024 году?")
print(responses)
competitor_analysis = agent.run("Проанализируй компанию OpenAI - какие у них основные продукты?")
print(competitor_analysis)
import schedule
import time
from datetime import datetime
class AutoUpdatingRAG:
"""RAG система с автоматическим обновлением"""
def __init__(self, firecrawl_api_key: str, openai_api_key: str):
self.firecrawl_key = firecrawl_api_key
self.openai_key = openai_api_key
self.topics = []
self.vectorstore = None
self.qa_chain = None
self.last_update = None
def add_topics(self, topics: list):
"""Добавить темы для отслеживания"""
self.topics.extend(topics)
def update_knowledge_base(self):
"""Обновление базы знаний"""
print(f"Обновление знаний в {datetime.now()}")
all_documents = []
# Загружаем свежие данные по всем темам
for topic in self.topics:
loader = FirecrawlLoader(
api_key=self.firecrawl_key,
search_query=topic
)
documents = loader.load()
# Добавляем тему в метаданные
for doc in documents:
doc.metadata['topic'] = topic
doc.metadata['updated_at'] = datetime.now().isoformat()
all_documents.extend(documents)
if all_documents:
# Пересоздаем векторное хранилище
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=200
)
splits = text_splitter.split_documents(all_documents)
embeddings = OpenAIEmbeddings(openai_api_key=self.openai_key)
self.vectorstore = Chroma.from_documents(splits, embeddings)
# Пересоздаем QA цепочку
llm = OpenAI(openai_api_key=self.openai_key, temperature=0)
self.qa_chain = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff",
retriever=self.vectorstore.as_retriever(search_kwargs={"k": 5}),
return_source_documents=True
)
self.last_update = datetime.now()
print(f"Обновлено {len(all_documents)} документов")
def query(self, question: str) -> dict:
"""Запрос к RAG системе"""
if not self.qa_chain:
self.update_knowledge_base()
result = self.qa_chain({"query": question})
# Добавляем информацию о свежести данных
result['knowledge_updated_at'] = self.last_update.isoformat() if self.last_update else None
result['topics_tracked'] = self.topics
return result
def start_auto_update(self, hours: int = 24):
"""Запуск автоматического обновления"""
schedule.every(hours).hours.do(self.update_knowledge_base)
print(f"Автообновление настроено на каждые {hours} часов")
# Первоначальное обновление
self.update_knowledge_base()
# Планировщик
while True:
schedule.run_pending()
time.sleep(3600) # Проверка каждый час
# Использование автообновляемой RAG
auto_rag = AutoUpdatingRAG(
firecrawl_api_key="your_firecrawl_key",
openai_api_key="your_openai_key"
)
# Добавляем темы для отслеживания
auto_rag.add_topics([
"искусственный интеллект новости",
"стартапы технологии",
"блокчейн разработка",
"веб-разработка тренды"
])
# Запросы с актуальными данными
result = auto_rag.query("Какие новые AI модели появились недавно?")
print(result['result'])
print(f"Данные обновлены: {result['knowledge_updated_at']}")
# Запуск автообновления (блокирующий вызов)
# auto_rag.start_auto_update(hours=12)
class CompetitorRAG:
def __init__(self, firecrawl_api_key: str, openai_api_key: str):
self.firecrawl_key = firecrawl_api_key
self.openai_key = openai_api_key
self.competitors = []
def add_competitors(self, competitors: list):
"""Добавить конкурентов для отслеживания"""
self.competitors = competitors
def create_competitive_intelligence(self):
"""Создание системы конкурентной разведки"""
all_docs = []
for competitor in self.competitors:
# Ищем информацию о конкуренте
loader = FirecrawlLoader(
api_key=self.firecrawl_key,
search_query=f"{competitor} продукты услуги цены новости"
)
docs = loader.load()
for doc in docs:
doc.metadata['competitor'] = competitor
all_docs.extend(docs)
# Создаем специализированную RAG для конкурентов
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000)
splits = text_splitter.split_documents(all_docs)
embeddings = OpenAIEmbeddings(openai_api_key=self.openai_key)
vectorstore = Chroma.from_documents(splits, embeddings)
llm = OpenAI(openai_api_key=self.openai_key)
# Специальный промпт для конкурентного анализа
prompt_template = """
Используй следующую информацию о конкурентах для ответа на вопрос.
Фокусируйся на сравнении, ценах, продуктах и конкурентных преимуществах.
Контекст: {context}
Вопрос: {question}
Подробный анализ:
"""
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
retriever=vectorstore.as_retriever(),
return_source_documents=True,
chain_type_kwargs={
"prompt": PromptTemplate.from_template(prompt_template)
}
)
return qa_chain
# Использование
competitor_rag = CompetitorRAG("firecrawl_key", "openai_key")
competitor_rag.add_competitors(["OpenAI", "Anthropic", "Google AI"])
intelligence_system = competitor_rag.create_competitive_intelligence()
analysis = intelligence_system({
"query": "Сравни цены и возможности AI продуктов конкурентов"
})
class NewsAnalyticsRAG:
def __init__(self, firecrawl_api_key: str, openai_api_key: str):
self.firecrawl_key = firecrawl_api_key
self.openai_key = openai_api_key
def create_news_analyzer(self, topics: list):
"""Создание аналитики новостей"""
# Загрузка новостей по темам
all_news = []
for topic in topics:
loader = FirecrawlLoader(
api_key=self.firecrawl_key,
search_query=f"{topic} новости"
)
news_docs = loader.load()
for doc in news_docs:
doc.metadata['news_topic'] = topic
doc.metadata['analysis_date'] = datetime.now().isoformat()
all_news.extend(news_docs)
# Специализированная обработка для новостей
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=800,
chunk_overlap=100
)
news_splits = text_splitter.split_documents(all_news)
embeddings = OpenAIEmbeddings(openai_api_key=self.openai_key)
news_vectorstore = Chroma.from_documents(news_splits, embeddings)
llm = OpenAI(openai_api_key=self.openai_key, temperature=0.3)
news_prompt = """
Анализируй новости как профессиональный аналитик.
Выявляй тренды, делай прогнозы, указывай влияние на рынок.
Новости: {context}
Вопрос: {question}
Аналитический ответ:
"""
return RetrievalQA.from_chain_type(
llm=llm,
retriever=news_vectorstore.as_retriever(search_kwargs={"k": 8}),
chain_type_kwargs={
"prompt": PromptTemplate.from_template(news_prompt)
},
return_source_documents=True
)
# Использование новостной аналитики
news_analyzer = NewsAnalyticsRAG("firecrawl_key", "openai_key")
news_rag = news_analyzer.create_news_analyzer([
"искусственный интеллект",
"блокчейн технологии",
"стартапы инвестиции"
])
trend_analysis = news_rag({
"query": "Какие технологические тренды будут доминировать в 2025 году?"
})
print(trend_analysis['result'])
class RAGMetrics:
def __init__(self):
self.query_history = []
self.source_quality = {}
def log_query(self, query: str, result: dict, response_time: float):
"""Логирование запросов"""
self.query_history.append({
'timestamp': datetime.now(),
'query': query,
'sources_count': len(result.get('source_documents', [])),
'response_time': response_time,
'confidence': self._calculate_confidence(result)
})
def _calculate_confidence(self, result: dict) -> float:
"""Расчет уверенности в ответе"""
# Простая метрика на основе количества источников
sources_count = len(result.get('source_documents', []))
return min(sources_count * 0.2, 1.0)
def get_analytics(self) -> dict:
"""Получение аналитики использования"""
if not self.query_history:
return {}
df = pd.DataFrame(self.query_history)
return {
'total_queries': len(df),
'avg_response_time': df['response_time'].mean(),
'avg_sources_per_query': df['sources_count'].mean(),
'avg_confidence': df['confidence'].mean(),
'queries_per_day': len(df[df['timestamp'] >= datetime.now().date()])
}
# Интеграция метрик в RAG
def enhanced_rag_query(rag_system, query: str, metrics: RAGMetrics):
"""Запрос с метриками"""
start_time = time.time()
result = rag_system({"query": query})
response_time = time.time() - start_time
metrics.log_query(query, result, response_time)
return result
# Использование с метриками
metrics = RAGMetrics()
result = enhanced_rag_query(rag_system, "Вопрос", metrics)
# Аналитика
analytics = metrics.get_analytics()
print(f"Аналитика RAG: {analytics}")