mirror of
https://github.com/semantica-agi/semantica.git
synced 2026-08-29 04:26:20 +00:00
27 KiB
27 KiB
In [ ]:
%pip install -qU semantica networkx matplotlib plotly pandas faiss-cpu beautifulsoup4 groq sentence-transformers scikit-learn
In [ ]:
import os
os.environ["GROQ_API_KEY"] = os.getenv("GROQ_API_KEY", "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")
# Configuration constants
EMBEDDING_DIMENSION = 384
EMBEDDING_MODEL = "all-MiniLM-L6-v2"
CHUNK_SIZE = 1000
CHUNK_OVERLAP = 200
In [ ]:
from semantica.ingest import MCPIngestor, WebIngestor, FeedIngestor, FileIngestor
import os
from contextlib import redirect_stderr
from io import StringIO
os.makedirs("data", exist_ok=True)
feed_sources = [
# Financial RSS Feeds - More reliable sources
("Yahoo Finance", "https://feeds.finance.yahoo.com/rss/2.0/headline"),
("Financial Times", "https://www.ft.com/?format=rss"),
("Bloomberg", "https://feeds.bloomberg.com/markets/news.rss"),
("MarketWatch", "https://feeds.marketwatch.com/marketwatch/markets"),
("Seeking Alpha", "https://seekingalpha.com/feed.xml"),
("Investing.com", "https://www.investing.com/rss/news.rss"),
("Financial News", "https://www.fnlondon.com/rss"),
("Wall Street Journal", "https://feeds.a.dj.com/rss/RSSMarketsMain.xml"),
]
feed_ingestor = FeedIngestor()
all_documents = []
print(f"Ingesting from {len(feed_sources)} feed sources...")
for i, (feed_name, feed_url) in enumerate(feed_sources, 1):
try:
with redirect_stderr(StringIO()):
feed_data = feed_ingestor.ingest_feed(feed_url, validate=False)
feed_count = 0
for item in feed_data.items:
if not item.content:
item.content = item.description or item.title or ""
if item.content:
if not hasattr(item, 'metadata'):
item.metadata = {}
item.metadata['source'] = feed_name
all_documents.append(item)
feed_count += 1
if feed_count > 0:
print(f" [{i}/{len(feed_sources)}] {feed_name}: {feed_count} documents")
except Exception:
continue
# Example: Ingest from Alpha Vantage API (requires API key)
alpha_vantage_api = "https://www.alphavantage.co/query?function=GLOBAL_QUOTE&symbol=AAPL&apikey=demo"
try:
web_ingestor = WebIngestor()
with redirect_stderr(StringIO()):
api_documents = web_ingestor.ingest(alpha_vantage_api, method="url")
for doc in api_documents:
if not hasattr(doc, 'metadata'):
doc.metadata = {}
doc.metadata['source'] = 'Alpha Vantage API'
all_documents.append(doc)
except Exception:
pass
# MCP Server connection example (commented for demo)
# mcp_ingestor = MCPIngestor()
# mcp_ingestor.connect("financial_server", url="http://localhost:8000/mcp")
# resources = mcp_ingestor.list_available_resources("financial_server")
# mcp_data = mcp_ingestor.ingest_resources("financial_server", resource_uris=["resource://market_data"])
if not all_documents:
market_data = """
AAPL stock price: $150.25, market cap: $2.4T, volume: 50M shares, sector: Technology
MSFT stock price: $380.50, market cap: $2.8T, volume: 30M shares, sector: Technology
GOOGL stock price: $140.75, market cap: $1.8T, volume: 25M shares, sector: Technology
JPM stock price: $145.30, market cap: $420B, volume: 15M shares, sector: Financial
"""
with open("data/market_data.txt", "w") as f:
f.write(market_data)
file_ingestor = FileIngestor()
all_documents = file_ingestor.ingest("data/market_data.txt")
documents = all_documents
print(f"Ingested {len(documents)} documents")
In [ ]:
from semantica.seed import SeedDataManager
seed_manager = SeedDataManager()
# Load foundation market data (exchanges, indices, sectors)
seed_data = [
{"type": "Market", "text": "NASDAQ", "description": "Stock exchange"},
{"type": "Market", "text": "NYSE", "description": "Stock exchange"},
{"type": "Market", "text": "S&P 500", "description": "Stock market index"},
{"type": "Sector", "text": "Technology", "description": "Market sector"},
{"type": "Sector", "text": "Financial", "description": "Market sector"},
{"type": "Sector", "text": "Healthcare", "description": "Market sector"},
]
# Add seed data as entities
for item in seed_data:
entity = {
"id": item.get("text", "").lower().replace(" ", "_"),
"text": item.get("text", ""),
"name": item.get("text", ""),
"type": item.get("type", ""),
"description": item.get("description", ""),
"source": "seed_data"
}
seed_manager.seed_data.entities.append(entity)
print(f"Loaded {len(seed_data)} seed data items for market foundation")
In [ ]:
from semantica.parse import DocumentParser
parser = DocumentParser()
print(f"Parsing {len(documents)} documents...")
parsed_documents = []
for i, doc in enumerate(documents, 1):
try:
parsed = parser.parse(
doc.content if hasattr(doc, 'content') else str(doc),
content_type="text"
)
parsed_documents.append(parsed)
except Exception:
parsed_documents.append(doc)
if i % 50 == 0 or i == len(documents):
print(f" Parsed {i}/{len(documents)} documents...")
documents = parsed_documents
In [ ]:
from semantica.normalize import TextNormalizer
from semantica.split import TextSplitter
normalizer = TextNormalizer()
# Use recursive chunking for financial documents
splitter = TextSplitter(method="recursive", chunk_size=CHUNK_SIZE, chunk_overlap=CHUNK_OVERLAP)
print(f"Normalizing {len(documents)} documents...")
normalized_documents = []
for i, doc in enumerate(documents, 1):
normalized_text = normalizer.normalize(
doc.content if hasattr(doc, 'content') else str(doc),
clean_html=True,
normalize_entities=True,
normalize_numbers=True,
remove_extra_whitespace=True,
lowercase=False
)
normalized_documents.append(normalized_text)
if i % 50 == 0 or i == len(documents):
print(f" Normalized {i}/{len(documents)} documents...")
print(f"Chunking {len(normalized_documents)} documents...")
chunked_documents = []
for i, doc_text in enumerate(normalized_documents, 1):
try:
with redirect_stderr(StringIO()):
chunks = splitter.split(doc_text)
chunked_documents.extend(chunks)
except Exception:
simple_splitter = TextSplitter(method="recursive", chunk_size=CHUNK_SIZE, chunk_overlap=CHUNK_OVERLAP)
chunks = simple_splitter.split(doc_text)
chunked_documents.extend(chunks)
if i % 50 == 0 or i == len(normalized_documents):
print(f" Chunked {i}/{len(normalized_documents)} documents ({len(chunked_documents)} chunks so far)")
print(f"Created {len(chunked_documents)} chunks from {len(normalized_documents)} documents")
In [ ]:
from semantica.semantic_extract import NERExtractor
entity_extractor = NERExtractor(
method="ml",
model="en_core_web_sm"
)
all_entities = []
print(f"Extracting entities from {len(chunked_documents)} chunks...")
for i, chunk in enumerate(chunked_documents, 1):
chunk_text = chunk.text if hasattr(chunk, 'text') else str(chunk)
try:
entities = entity_extractor.extract_entities(chunk_text)
all_entities.extend(entities)
except Exception:
continue
if i % 20 == 0 or i == len(chunked_documents):
print(f" Processed {i}/{len(chunked_documents)} chunks ({len(all_entities)} entities found)")
# Categorize entities using spaCy's standard types (ORG, GPE, MONEY, etc.)
companies = [e for e in all_entities if e.label in ["ORG", "ORGANIZATION"]]
markets = [e for e in all_entities if e.label in ["GPE", "LOCATION", "LOC"]]
prices = [e for e in all_entities if e.label in ["MONEY", "CURRENCY"]]
metrics = [e for e in all_entities if e.label in ["CARDINAL", "QUANTITY", "PERCENT", "PERCENTAGE"]]
print(f"Extracted {len(companies)} companies/organizations, {len(markets)} markets/locations, {len(prices)} prices, {len(metrics)} metrics")
In [ ]:
from semantica.semantic_extract import RelationExtractor
relation_extractor = RelationExtractor(
method="dependency",
model="en_core_web_sm"
)
all_relationships = []
print(f"Extracting relationships from {len(chunked_documents)} chunks...")
for i, chunk in enumerate(chunked_documents, 1):
chunk_text = chunk.text if hasattr(chunk, 'text') else str(chunk)
try:
relationships = relation_extractor.extract_relations(
chunk_text,
entities=all_entities,
relation_types=["trades_on", "has_price", "belongs_to", "correlates_with", "has_metric", "in_sector"]
)
all_relationships.extend(relationships)
except Exception:
continue
if i % 20 == 0 or i == len(chunked_documents):
print(f" Processed {i}/{len(chunked_documents)} chunks ({len(all_relationships)} relationships found)")
print(f"Extracted {len(all_relationships)} relationships")
In [ ]:
from semantica.conflicts import ConflictDetector, ConflictResolver
conflict_detector = ConflictDetector()
conflict_resolver = ConflictResolver()
# Convert Entity objects to dictionaries for conflict detection
entity_dicts = [
{
"id": e.text if hasattr(e, 'text') else str(e),
"text": e.text if hasattr(e, 'text') else str(e),
"name": e.text if hasattr(e, 'text') else str(e),
"type": e.label if hasattr(e, 'label') else "ENTITY",
"confidence": e.confidence if hasattr(e, 'confidence') else 1.0,
"metadata": e.metadata if hasattr(e, 'metadata') else {},
"source": e.metadata.get("source", "unknown") if hasattr(e, 'metadata') and isinstance(e.metadata, dict) else "unknown"
}
for e in all_entities
]
print(f"Detecting temporal conflicts in {len(entity_dicts)} entities...")
conflicts = conflict_detector.detect_temporal_conflicts(entity_dicts)
print(f"Detected {len(conflicts)} temporal conflicts")
if conflicts:
print(f"Resolving conflicts using most_recent strategy...")
resolved = conflict_resolver.resolve_conflicts(
conflicts,
strategy="most_recent"
)
print(f"Resolved {len(resolved)} conflicts")
else:
print("No conflicts detected")
In [ ]:
from semantica.kg import EntityResolver
from semantica.semantic_extract import Entity
# Convert Entity objects to dictionaries for EntityResolver
print(f"Converting {len(all_entities)} entities to dictionaries...")
entity_dicts = [{"name": e.text, "type": e.label, "start_char": getattr(e, 'start_char', 0), "end_char": getattr(e, 'end_char', 0), "confidence": e.confidence} for e in all_entities]
# Use EntityResolver class to resolve duplicates
entity_resolver = EntityResolver(strategy="fuzzy", similarity_threshold=0.85)
print(f"Resolving duplicates in {len(entity_dicts)} entities...")
resolved_entities = entity_resolver.resolve_entities(entity_dicts)
# Convert back to Entity objects
print(f"Converting {len(resolved_entities)} resolved entities back to Entity objects...")
merged_entities = [
Entity(text=e["name"], label=e["type"], start_char=e.get("start_char", 0), end_char=e.get("end_char", 0), confidence=e.get("confidence", 1.0))
for e in resolved_entities
]
# Enhance entities with seed data information
for entity in merged_entities:
for seed_item in seed_data:
if entity.text.lower() == seed_item["text"].lower():
entity.description = seed_item.get("description", "")
break
print(f"Deduplicated {len(entity_dicts)} entities to {len(merged_entities)} unique entities")
In [ ]:
from semantica.kg import GraphBuilder
graph_builder = GraphBuilder()
print(f"Building knowledge graph...")
kg_sources = [{
"entities": [{"text": e.text, "type": e.label, "confidence": e.confidence} for e in merged_entities],
"relationships": [{"source": r.subject.text, "target": r.object.text, "type": r.predicate, "confidence": r.confidence} for r in all_relationships]
}]
kg = graph_builder.build(kg_sources)
entities_count = len(kg.get('entities', []))
relationships_count = len(kg.get('relationships', []))
print(f"Graph: {entities_count} entities, {relationships_count} relationships")
In [ ]:
from semantica.embeddings import EmbeddingGenerator
embedding_gen = EmbeddingGenerator(
provider="sentence_transformers",
model=EMBEDDING_MODEL
)
print(f"Generating embeddings for {len(companies)} companies and {len(markets)} markets...")
company_texts = [c.text for c in companies]
company_embeddings = embedding_gen.generate_embeddings(company_texts)
market_texts = [m.text for m in markets]
market_embeddings = embedding_gen.generate_embeddings(market_texts)
print(f"Generated {len(company_embeddings)} company embeddings and {len(market_embeddings)} market embeddings")
In [ ]:
from semantica.vector_store import VectorStore
vector_store = VectorStore(backend="faiss", dimension=EMBEDDING_DIMENSION)
print(f"Storing {len(company_embeddings)} company vectors and {len(market_embeddings)} market vectors...")
company_ids = vector_store.store_vectors(
vectors=company_embeddings,
metadata=[{"type": "company", "name": c.text, "label": c.label} for c in companies]
)
market_ids = vector_store.store_vectors(
vectors=market_embeddings,
metadata=[{"type": "market", "name": m.text, "label": m.label} for m in markets]
)
print(f"Stored {len(company_ids)} company vectors and {len(market_ids)} market vectors")
In [ ]:
from semantica.kg import GraphAnalyzer, CentralityCalculator
graph_analyzer = GraphAnalyzer()
centrality_calc = CentralityCalculator()
analysis = graph_analyzer.analyze_graph(kg)
degree_centrality = centrality_calc.calculate_degree_centrality(kg)
betweenness_centrality = centrality_calc.calculate_betweenness_centrality(kg)
closeness_centrality = centrality_calc.calculate_closeness_centrality(kg)
# Identify central entities in the market network
central_entities = []
for entity in kg.get("entities", []):
entity_id = entity.get("id")
if entity_id in degree_centrality:
central_entities.append({
"name": entity.get("text", "Unknown"),
"type": entity.get("type", "Unknown"),
"degree": degree_centrality[entity_id]
})
central_entities.sort(key=lambda x: x['degree'], reverse=True)
print(f"Graph analytics:")
print(f" - Graph density: {analysis.get('density', 0):.3f}")
print(f" - Central nodes (degree): {len(degree_centrality)}")
print(f" - Total entities: {len(kg.get('entities', []))}")
print(f" - Total relationships: {len(kg.get('relationships', []))}")
if central_entities:
print(f"\nTop 5 central entities:")
for i, ent in enumerate(central_entities[:5], 1):
print(f" {i}. {ent['name']} ({ent['type']}) - Degree: {ent['degree']:.3f}")
In [ ]:
from semantica.context import AgentContext
from semantica.llms import Groq
import os
context = AgentContext(
vector_store=vector_store,
knowledge_graph=kg,
max_expansion_hops=3,
hybrid_alpha=0.7
)
# Initialize Groq LLM
llm = Groq(model="llama-3.1-8b-instant", api_key=os.getenv("GROQ_API_KEY"))
query = "What technology companies are in the market and what are their key relationships?"
print(f"{'='*80}")
print(f"GraphRAG Query: {query}")
print(f"{'='*80}\n")
# Use multi-hop reasoning with LLM generation
result = context.query_with_reasoning(
query=query,
llm_provider=llm,
max_results=15,
max_hops=3,
min_score=0.2
)
print("=" * 80)
print("Generated Answer (with Multi-hop Reasoning):")
print("=" * 80)
response = result.get('response', 'No response generated')
print(response)
print("\n" + "=" * 80)
print(f"\nReasoning Details:")
print(f"- Confidence: {result.get('confidence', 0):.3f}")
print(f"- Sources: {result.get('num_sources', 0)}")
print(f"- Reasoning Paths: {result.get('num_reasoning_paths', 0)}")
print(f"- Total entities in graph: {len(kg.get('entities', []))}")
print(f"- Total relationships in graph: {len(kg.get('relationships', []))}")
if result.get('sources'):
print(f"\nTop Sources:")
for i, source in enumerate(result['sources'][:5], 1):
content = source.get('content', '')[:200] if isinstance(source, dict) else str(source)[:200]
score = source.get('score', 0) if isinstance(source, dict) else 0
print(f" {i}. Score: {score:.3f}")
print(f" {content}...")
In [ ]:
from semantica.export import GraphExporter
exporter = GraphExporter()
exporter.export(kg, output_path="financial_data_kg.json", format="json")
exporter.export(kg, output_path="financial_data_kg.graphml", format="graphml")
print("Exported financial knowledge graph to JSON, GraphML, and CSV formats")