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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions