Skip to content

ИИ‑ассистент для сбора информации: расширенная версия с поддержкой соцсетей #331

@myltik1702

Description

@myltik1702

ИИ‑ассистент для сбора информации: расширенная версия с поддержкой соцсетей

Ниже — доработанный код ассистента, который умеет собирать данные из соцсетей (на примере API VK и Telegram) и комбинировать их с локальными данными.

1. Обновлённые зависимости

Добавьте библиотеки для работы с API соцсетей:

npm install axios querystring dotenv-expand

2. Обновлённый .env (с ключами соцсетей)

OPENAI_API_KEY=sk-your-openai-api-key-here
PORT=3000

# VK API
VK_API_KEY=your-vk-api-key
VK_GROUP_ID=123456789


# Telegram Bot (опционально)
TELEGRAM_BOT_TOKEN=your-telegram-bot-token
TELEGRAM_CHAT_ID=your-chat-id

3. Обновлённый server.js (с интеграцией соцсетей)

require('dotenv').config();
const express = require('express');
const { OpenAI } = require('openai');
const fs = require('fs');
const path = require('path');
const axios = require('axios');
const querystring = require('querystring');

const app = express();
app.use(express.json());

// Инициализация OpenAI
const openai = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY,
});

// Промежуточное ПО для логирования
app.use((req, res, next) => {
  console.log(`[${new Date().toISOString()}] ${req.method} ${req.path}`);
  next();
});

// Функция: загрузка локальных данных
async function loadLocalData() {
  const dataPath = path.join(__dirname, 'data', 'sample_data.json');
  const data = fs.readFileSync(dataPath, 'utf8');
  return JSON.parse(data);
}

// Функция: получение постов из VK
async function fetchVKPosts() {
  try {
    const params = {
      owner_id: `-${process.env.VK_GROUP_ID}`,
      count: 5,
      access_token: process.env.VK_API_KEY,
      v: '5.131'
    };
    
    const response = await axios.get(
      'https://api.vk.com/method/wall.get',
      { params }
    );
    
    return response.data.response.items.map(post => ({
      id: post.id,
      text: post.text,
      date: new Date(post.date * 1000).toISOString(),
      likes: post.likes.count
    }));
  } catch (error) {
    console.error('Ошибка при запросе к VK API:', error.message);
    return [];
  }
}

// Функция: комбинированный сбор данных
async function gatherAllData() {
  const [localData, vkPosts] = await Promise.all([
    loadLocalData(),
    fetchVKPosts()
  ]);
  
  return {
    local: localData,
    social: { vk: vkPosts },
    timestamp: new Date().toISOString()
  };
}

// Функция: запрос к OpenAI с мульти-источником
async function askOpenAI(prompt, context) {
  const completion = await openai.chat.completions.create({
    model: 'gpt-4-turbo', // лучше для анализа разнородных данных
    messages: [
      {
        role: 'system',
        content: `Ты — ассистент по сбору информации. Анализируй данные из разных источников (локальные данные, соцсети). 
        Если информации нет — скажи "Данных недостаточно". Отвечай кратко и по делу.`
      },
      { 
        role: 'user',
        content: `Контекст:\n${JSON.stringify(context, null, 2)}\n\nВопрос:\n${prompt}`
      }
    ],
    temperature: 0.2,
    max_tokens: 1500,
  });
  return completion.choices[0].message.content;
}

// Маршрут: задать вопрос ассистенту
app.post('/ask', async (req, res) => {
  try {
    const { question } = req.body;

    if (!question) {
      return res.status(400).json({ error: 'Поле "question" обязательно' });
    }

    // Собираем все данные
    const allData = await gatherAllData();

    // Отправляем запрос в OpenAI
    const answer = await askOpenAI(question, allData);

    res.json({ 
      answer,
      sources: {
        local: allData.local ? 'доступно' : 'нет данных',
        vk: allData.social.vk.length > 0 ? `${allData.social.vk.length} постов` : 'нет данных'
      }
    });
  } catch (error) {
    console.error('Ошибка:', error);
    res.status(500).json({ error: 'Произошла ошибка на сервере' });
  }
});

// Маршрут: проверка здоровья
app.get('/health', (req, res) => {
  res.json({ status: 'ok', timestamp: new Date().toISOString() });
});

// Маршрут: ручной сбор данных (для отладки)
app.get('/data', async (req, res) => {
  try {
    const data = await gatherAllData();
    res.json(data);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Запуск сервера
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Сервер запущен на порту ${PORT}`);
  console.log('Доступные маршруты:');
  console.log('  POST /ask — задать вопрос');
  console.log('  GET /health — проверка состояния');
  console.log('  GET /data — получить все собранные данные');
});

4. Тестирование расширенной версии

  1. Запустите сервер:
node server.js
  1. Проверьте сбор данных:
curl http://localhost:3000/data
  1. Задайте вопрос с учётом соцсетей:
curl -X POST http://localhost:3000/ask \
  -H "Content-Type: application/json" \
  -d '{"question": "Какие темы обсуждаются в группе VK за последнюю неделю?"}'

Пример ответа:

{
  "answer": "В группе VK обсуждаются: 1) обновление API, 2) планы по релизу CRM, 3) вопросы безопасности.",
  "sources": {
    "local": "доступно",
    "vk": "5 постов"
  }
}

5. Дополнительные интеграции

Для Telegram (бот)

Добавьте маршрут для приёма сообщений:

app.post('/telegram-hook', async (req, res) => {
  const message = req.body.message.text;
  const answer = await askOpenAI(message, await gatherAllData());
  
  // Отправка ответа через Telegram Bot API
  await axios.post(
    `https://api.telegram.org/bot${process.env.TELEGRAM_BOT_TOKEN}/sendMessage`,
    {
      chat_id: process.env.TELEGRAM_CHAT_ID,
      text: answer
    }
  );
  res.status(200).send('OK');
});

Для других соцсетей

  • Twitter/X: используйте twitter-api-v2.
  • LinkedIn: официальный API или axios с OAuth2.
  • Одноклассники: API через axios.

6. Рекомендации по безопасности

  1. Ограничение доступа к API:

    // Middleware для API-ключей
    app.use('/ask', (req, res, next) => {
      const apiKey = req.headers['x-api-key'];
      if (apiKey !== process.env.API_SECRET) {
        return res.status(401).json({ error: 'Неавторизованно' });
      }
      next();
    });
  2. Валидация входных данных:

    const { body } = req;
    if (typeof body.question !== 'string' || body.question.length > 1000) {
      return res.status(400).json({ error:

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions