Squashed 'vendor/ruvector/' content from commit b64c2172
git-subtree-dir: vendor/ruvector git-subtree-split: b64c21726f2bb37286d9ee36a7869fef60cc6900
This commit is contained in:
@@ -0,0 +1,223 @@
|
||||
/**
|
||||
* Social network generator using OpenRouter/Kimi K2
|
||||
*/
|
||||
|
||||
import { OpenRouterClient } from '../openrouter-client.js';
|
||||
import {
|
||||
SocialNetworkOptions,
|
||||
SocialNode,
|
||||
GraphData,
|
||||
GraphNode,
|
||||
GraphEdge,
|
||||
GraphGenerationResult
|
||||
} from '../types.js';
|
||||
|
||||
interface ConnectionData {
|
||||
source: string;
|
||||
target: string;
|
||||
type: string;
|
||||
properties?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
export class SocialNetworkGenerator {
|
||||
constructor(private client: OpenRouterClient) {}
|
||||
|
||||
/**
|
||||
* Generate a social network graph
|
||||
*/
|
||||
async generate(options: SocialNetworkOptions): Promise<GraphGenerationResult<GraphData>> {
|
||||
const startTime = Date.now();
|
||||
|
||||
// Generate users
|
||||
const users = await this.generateUsers(options);
|
||||
|
||||
// Generate connections based on network type
|
||||
const connections = await this.generateConnections(users, options);
|
||||
|
||||
// Convert to graph structure
|
||||
const nodes: GraphNode[] = users.map(user => ({
|
||||
id: user.id,
|
||||
labels: ['User'],
|
||||
properties: {
|
||||
username: user.username,
|
||||
...user.profile,
|
||||
...(user.metadata || {})
|
||||
}
|
||||
}));
|
||||
|
||||
const edges: GraphEdge[] = connections.map((conn, idx) => ({
|
||||
id: `connection_${idx}`,
|
||||
type: conn.type || 'FOLLOWS',
|
||||
source: conn.source,
|
||||
target: conn.target,
|
||||
properties: conn.properties || {}
|
||||
}));
|
||||
|
||||
const data: GraphData = {
|
||||
nodes,
|
||||
edges,
|
||||
metadata: {
|
||||
domain: 'social-network',
|
||||
generated_at: new Date(),
|
||||
total_nodes: nodes.length,
|
||||
total_edges: edges.length
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
data,
|
||||
metadata: {
|
||||
generated_at: new Date(),
|
||||
model: this.client.getConfig().model || 'moonshot/kimi-k2-instruct',
|
||||
duration: Date.now() - startTime
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate realistic social network users
|
||||
*/
|
||||
private async generateUsers(options: SocialNetworkOptions): Promise<SocialNode[]> {
|
||||
const systemPrompt = 'You are an expert at creating realistic social network user profiles. Generate diverse, believable users.';
|
||||
|
||||
const userPrompt = `Generate ${options.users} realistic social network user profiles.
|
||||
|
||||
Each user should have:
|
||||
- id: unique user ID (format: user_XXXXX)
|
||||
- username: unique username
|
||||
- profile: object with name, bio, joined (ISO date), followers (number), following (number)
|
||||
${options.includeMetadata ? '- metadata: additional information like interests, location, verified status' : ''}
|
||||
|
||||
Make the profiles diverse and realistic. Return a JSON array.
|
||||
|
||||
Example format:
|
||||
\`\`\`json
|
||||
[
|
||||
{
|
||||
"id": "user_12345",
|
||||
"username": "tech_enthusiast_42",
|
||||
"profile": {
|
||||
"name": "Alex Johnson",
|
||||
"bio": "Software developer passionate about AI and open source",
|
||||
"joined": "2020-03-15T00:00:00Z",
|
||||
"followers": 1250,
|
||||
"following": 430
|
||||
}${options.includeMetadata ? `,
|
||||
"metadata": {
|
||||
"interests": ["technology", "AI", "coding"],
|
||||
"location": "San Francisco, CA",
|
||||
"verified": false
|
||||
}` : ''}
|
||||
}
|
||||
]
|
||||
\`\`\``;
|
||||
|
||||
return this.client.generateStructured<SocialNode[]>(
|
||||
systemPrompt,
|
||||
userPrompt,
|
||||
{
|
||||
temperature: 0.9,
|
||||
maxTokens: Math.min(8000, options.users * 150)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate connections between users
|
||||
*/
|
||||
private async generateConnections(
|
||||
users: SocialNode[],
|
||||
options: SocialNetworkOptions
|
||||
): Promise<ConnectionData[]> {
|
||||
const totalConnections = Math.floor(options.users * options.avgConnections / 2);
|
||||
|
||||
const systemPrompt = `You are an expert at modeling social network connections. Create realistic ${options.networkType || 'random'} network patterns.`;
|
||||
|
||||
const userList = users.slice(0, 100).map(u => `- ${u.id}: @${u.username}`).join('\n');
|
||||
|
||||
const userPrompt = `Given these social network users:
|
||||
|
||||
${userList}
|
||||
|
||||
Generate ${totalConnections} connections creating a ${options.networkType || 'random'} network structure.
|
||||
|
||||
${this.getNetworkTypeGuidance(options.networkType)}
|
||||
|
||||
Each connection should have:
|
||||
- source: user id who initiates the connection
|
||||
- target: user id being connected to
|
||||
- type: connection type (FOLLOWS, FRIEND, BLOCKS, MUTES)
|
||||
- properties: optional properties like since (ISO date), strength (0-1)
|
||||
|
||||
Return a JSON array of connections.
|
||||
|
||||
Example format:
|
||||
\`\`\`json
|
||||
[
|
||||
{
|
||||
"source": "user_12345",
|
||||
"target": "user_67890",
|
||||
"type": "FOLLOWS",
|
||||
"properties": {
|
||||
"since": "2021-06-15T00:00:00Z",
|
||||
"strength": 0.8
|
||||
}
|
||||
}
|
||||
]
|
||||
\`\`\``;
|
||||
|
||||
return this.client.generateStructured<ConnectionData[]>(systemPrompt, userPrompt, {
|
||||
temperature: 0.7,
|
||||
maxTokens: Math.min(8000, totalConnections * 80)
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get guidance for network type
|
||||
*/
|
||||
private getNetworkTypeGuidance(networkType?: string): string {
|
||||
switch (networkType) {
|
||||
case 'small-world':
|
||||
return 'Create clusters of highly connected users with occasional bridges between clusters (small-world property).';
|
||||
case 'scale-free':
|
||||
return 'Create a power-law distribution where a few users have many connections (influencers) and most have few connections.';
|
||||
case 'clustered':
|
||||
return 'Create distinct communities/clusters with high internal connectivity and sparse connections between clusters.';
|
||||
default:
|
||||
return 'Create random connections with varying connection strengths.';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Analyze network properties
|
||||
*/
|
||||
async analyzeNetwork(data: GraphData): Promise<{
|
||||
avgDegree: number;
|
||||
maxDegree: number;
|
||||
communities?: number;
|
||||
clustering?: number;
|
||||
}> {
|
||||
const degrees = new Map<string, number>();
|
||||
|
||||
for (const edge of data.edges) {
|
||||
degrees.set(edge.source, (degrees.get(edge.source) || 0) + 1);
|
||||
degrees.set(edge.target, (degrees.get(edge.target) || 0) + 1);
|
||||
}
|
||||
|
||||
const degreeValues = Array.from(degrees.values());
|
||||
const avgDegree = degreeValues.reduce((a, b) => a + b, 0) / degreeValues.length;
|
||||
const maxDegree = Math.max(...degreeValues);
|
||||
|
||||
return {
|
||||
avgDegree,
|
||||
maxDegree
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a social network generator
|
||||
*/
|
||||
export function createSocialNetworkGenerator(client: OpenRouterClient): SocialNetworkGenerator {
|
||||
return new SocialNetworkGenerator(client);
|
||||
}
|
||||
Reference in New Issue
Block a user