{<Z Kordian Zadrożny

AI, Strony WWW, Programowanie, Bazy danych

Cześć 1: Bielik 11b v3 + typescript + langchain = Uczymy się i testujemy

utworzone przez | sty 5, 2026 | AI, kurs programowania, ogólnie, różne | 0 komentarzy

Wstęp

Z końcem roku pojawił się polski model SLM Bielik w wersji trzeciej, mający wsparcie dla tools, czyli narzędzi z których modele mogą korzystać. Moje krótki testy wykazały, że można bez problemu korzystać z niego za pomocą LM studio, w Ollama niestety trzeba parsować odpowiedzi ręcznie, co w przypadku planu nauki i używania frameworków (LangChain) do AI mija się troszkę z celem. Link do wątku na LinkedIn: https://www.linkedin.com

Projekt

Pomyślałem, jak go przetestować w jakimś real Case, i wpadłem na pomysł, asystenta do Wordpresa. W sumie, to można by potraktować Wordpresa jako bazę wiedzy dla bielika, oczywiście to w formie zabawy. A, że jestem w trakcie nauki TypeScripta, i wdrożenia się w to środowisko, pomyślałem, ze stworzę taki tutorial, korzystając oczywiście z innych źródeł wiedzy i ucząc się równocześnie.

Użyte technologie

Node.js i TypeScript

Node.js to środowisko uruchomieniowe JavaScript, które pozwala na wykonywanie kodu JavaScript poza przeglądarką. Używamy wersji 18 lub nowszej.

TypeScript to nadzbiór JavaScript dodający statyczne typowanie, co zwiększa bezpieczeństwo kodu i ułatwia jego utrzymanie. Kompilator TypeScript sprawdza typy podczas pisania kodu, co pozwala wychwycić błędy przed uruchomieniem aplikacji.

Bielik 11B v3.0 Instruct

Polski model językowy stworzony przez SpeakLeash i ACK Cyfronet AGH. Model wspiera 32 języki europejskie, z optymalizacją dla języka polskiego. Dostępny w różnych wersjach kwantyzacji:

  • Q5_K_M – mniejszy rozmiar (około 7.5 GB), szybsze działanie, dobra jakość
  • Q8_0 – większy rozmiar (około 11 GB), wyższa dokładność odpowiedzi

Model obsługuje wywołania narzędzi (function calling), co pozwala mu na wykonywanie konkretnych akcji zamiast tylko generowania tekstu.

LM Studio

Aplikacja desktopowa umożliwiająca uruchamianie modeli LLM lokalnie na własnym komputerze. Kluczowe cechy:

  • Udostępnia API kompatybilne z OpenAI (endpoint: http://127.0.0.1:1234/v1)
  • Obsługuje modele w formacie GGUF
  • Pozwala na kontrolę parametrów generowania (temperatura, top-p, itp.)
  • Działa offline – wszystko przetwarzane lokalnie

LangChain.js

Framework JavaScript/TypeScript i Pythona do budowania aplikacji wykorzystujących modele językowe. Oferuje:

  • Abstrakcję dla różnych dostawców LLM (OpenAI, Anthropic, lokalne modele)
  • Wsparcie dla narzędzi (tools) – definiowanie funkcji które model może wywoływać
  • Zarządzanie promptami i historią konwersacji
  • Integrację z różnymi źródłami danych

W naszym projekcie używamy LangChain do komunikacji z LM Studio i definiowania narzędzi WordPress.

Aplikacja działająca w konsoli, pozwalająca pytać o dane w wordpresie w języku naturalnym oraz dodawać posty.

Część 1: Przygotowanie projektu

Po Pierwsze, jeśli nie masz, to pobierz i zainstaluj NODE.JS: Node.js — Run JavaScript Everywhere

Po drugie, jeśli nie masz pobierz i zainstaluj VS Code (Albo użyj innego dowolnego edytora): Visual Studio Code – The open source AI code editor

Tworzymy nowy katalog i inicjalizujemy projekt Node.js:

konsola

mkdir bielik-wp
cd wp-ai-assistant
npm init -y

Co to robi?

  • mkdir – tworzy nowy katalog (folder) użyj taką nazwę jaka jest dla ciebie wygodna.
  • cd – wchodzi do katalogu
  • npm init -y – tworzy plik package.json z domyślnymi ustawieniami

package.json to plik konfiguracyjny, który zawiera informacje o projekcie i listę bibliotek (zależności), których używamy.

Edytuj go, i w scripts dodaj „start”: „tsx src/index.ts”,

Instalacja bibliotek

konsola

npm install @langchain/openai @langchain/core langchain axios dotenv zod
npm install -D typescript @types/node tsx

Wyjaśnienie bibliotek:

Biblioteki główne (dependencies):

  • @langchain/openai – łączy się z LM Studio (serwer AI)
  • @langchain/core – podstawowe narzędzia LangChain
  • langchain – główna biblioteka do pracy z AI
  • axios – wysyła zapytania HTTP do WordPress
  • dotenv – wczytuje zmienne z pliku .env (hasła, adresy)
  • zod – sprawdza poprawność danych (walidacja)

Biblioteki deweloperskie (-D):

  • typescript – kompilator TypeScript
  • @types/node – definicje typów dla Node.js
  • tsx – uruchamia pliki TypeScript bez kompilacji

W tej chwili nasz folder będzie wyglądał tak:

Konfiguracja TypeScript

Tworzymy plik tsconfig.json:

{
  "compilerOptions": {
    "target": "ES2020",           // Wersja JavaScript na wyjściu
    "module": "CommonJS",         // System modułów (require/exports)
    "strict": true,               // Ścisłe sprawdzanie typów
    "esModuleInterop": true,      // Kompatybilność z różnymi modułami
    "skipLibCheck": true,         // Pomija sprawdzanie bibliotek
    "forceConsistentCasingInFileNames": true,  // Wymusza spójność nazw
    "outDir": "./dist"            // Katalog dla skompilowanych plików
  },
  "include": ["src/**/*"]         // Które pliki kompilować
}

WordPress i dane dostępowe – Zmienne środowiskowe

Dla celów tego tutoriala utworzyłem w dhosting.pl którego używam nową instalację wordpresa.

Tworzymy plik .env z danymi dostępowymi:

WP_API_URL=https://twoja-domena.pl/wp-json/wp/v2
WP_USER=twoja-nazwa-uzytkownika
WP_PASSWORD=xxxx xxxx xxxx xxxx xxxx xxxx

Część 2: Moduł WordPress (wordpress.ts)

Tworzymy katalog src i plik src/wordpress.ts. Ten plik zawiera funkcje do komunikacji z WordPress.

Krok po kroku wpisujemy kod, i tłumaczę od razu co jest co.

import axios from 'axios';
import * as dotenv from 'dotenv';

dotenv.config();

Importujemy bibliotekę axios, która pozwala wysyłać zapytania HTTP do WordPress API. To jak przeglądarka, ale w kodzie. W Pythonie użył bym modułu requests.

Oraz ładujemy zmienne środowiskowe z pliku .env

Konfiguracja klienta HTTP

const client = axios.create({
  baseURL: process.env.WP_API_URL,
  auth: {
    username: process.env.WP_USER,
    password: process.env.WP_PASSWORD
  }
});

Wyjaśnienie linia po linii:

const client = axios.create({...})
Tworzymy „klienta” HTTP czyli obiekt, który będzie wysyłał zapytania do WordPress.

baseURL: process.env.WP_API_URL
Ustawiamy bazowy adres API. process.env to obiekt zawierający zmienne z pliku .env.

auth: { username: ..., password: ... }
Konfigurujemy uwierzytelnienie. Każde zapytanie będzie automatycznie zawierać te dane.

Definicja interfejsu

interface WPPost {
  id: number;
  title: { rendered: string };
  link: string;
  date: string;
}

Czym jest interface?
Interface to definicja opisująca kształt obiektu. Mówi TypeScript: „obiekt WPPost musi mieć te pola z tymi typami”.

Jeśli używałeś Pythona i Pydentic, to wyda się znajome, prawda? 🙂

Przykład:
id: number – pole „id” musi być liczbą
title: { rendered: string } – pole „title” to obiekt z polem „rendered” typu string

Dzięki temu TypeScript ostrzeże nas, jeśli spróbujemy użyć pola, którego nie ma.

Funkcja: createPost

export async function createPost(
  title: string, 
  content: string, 
  status: 'publish' | 'draft' = 'draft'
) {
  try {
    const response = await client.post('/posts', {
      title,
      content,
      status
    });
    return `Utworzono post: ${response.data.link} (ID: ${response.data.id})`;
  } catch (error: any) {
    return `Błąd podczas tworzenia wpisu: ${error.message}`;
  }
}

Wyjaśnienie szczegółowe:

export async function createPost(...)
– export – funkcja będzie dostępna w innych plikach
– async – funkcja asynchroniczna (może czekać na operacje)
– function createPost – nazwa funkcji

Parametry funkcji:
title: string – tytuł wpisu (musi być tekstem)
content: string – treść wpisu (też musi być tekstem)
status: 'publish' | 'draft' = 'draft' – status wpisu:
  – może być tylko „publish” lub „draft” (union type)
  – domyślna wartość to „draft” (jeśli nie podamy)

try { ... } catch (error) { ... }
Blok try-catch łapie błędy. Jeśli coś pójdzie nie tak w try, wykonuje się catch.

const response = await client.post('/posts', {...})
– await – czeka na zakończenie operacji
– client.post – wysyła zapytanie POST czyli wysyła paczkę danych, w pythonie był by requests.post
– '/posts' – endpoint API (doda się do baseURL)
– {title, content, status} – dane wysyłane do API

return Utworzono post: ${response.data.link}...
Template string (backticki)
pozwala wstawiać w JS/TS zmienne: ${zmienna} tak jak w pythonie byśmy uzyli f”zmienna: {zmienna}”

Funkcja: getRecentPosts

export async function getRecentPosts(count: number = 5) {
  try {
    const response = await client.get<WPPost[]>('/posts', {
      params: { per_page: count }
    });
    
    if (response.data.length === 0) {
      return "Nie znaleziono żadnych wpisów.";
    }

    return response.data.map(post => 
      `- [${post.id}] ${post.title.rendered} (${post.date})`
    ).join('\n');
  } catch (error: any) {
    return `Błąd pobierania wpisów: ${error.message}`;
  }
}

Nowe elementy:

count: number = 5
Parametr z wartością domyślną. Jeśli nie podamy, będzie 5.

client.get<WPPost[]>('/posts', {...})
– get – zapytanie GET (pobiera dane)
– <WPPost[]> – typ generyczny: spodziewamy się tablicy WPPost czyli inaczej zmiennej zawierającej wiele interfejsów które wcześniej zadeklarowaliśmy. W pythonie była by to lista słowników albo obiektów Pydantic.
– params: { per_page: count } – parametry URL (?per_page=5)

if (response.data.length === 0)
Sprawdzamy czy tablica jest pusta. === to ścisłe porównanie. W TS 2 == „2” da true a 2 === „2” false.

response.data.map(post => ...)
– map – przekształca każdy element tablicy
– post => ... – funkcja strzałkowa (arrow function)
– Dla każdego wpisu tworzymy string z jego danymi

.join('\n')
Łączy elementy tablicy w jeden string, oddzielając znakiem nowej linii.

Metoda map – przykład:

const numbers = [1, 2, 3];
const doubled = numbers.map(n => n * 2);
// Wynik: [2, 4, 6]

W naszym przypadku:

const posts = [{id: 1, title: "A"}, {id: 2, title: "B"}];
const formatted = posts.map(post => `- [${post.id}] ${post.title}`);
// Wynik: ["- [1] A", "- [2] B"]

Funkcja: searchPosts

export async function searchPosts(term: string) {
  try {
    const response = await client.get<WPPost[]>('/posts', {
      params: { search: term }
    });

    if (response.data.length === 0) {
      return `Nie znaleziono wpisów dla frazy "${term}".`;
    }

    return response.data.map(post => 
      `- [${post.id}] ${post.title.rendered}: ${post.link}`
    ).join('\n');
  } catch (error: any) {
    return `Błąd wyszukiwania: ${error.message}`;
  }
}

Podobna do getRecentPosts, ale:
– Używa parametru search: term zamiast per_page
– WordPress API wyszuka wpisy zawierające frazę w zmiennej term
– Wyświetla link do wpisu zamiast daty

Część 3: Główna aplikacja (index.ts)

Tworzymy plik src/index.ts – serce naszej aplikacji.

Importy

import { ChatOpenAI } from '@langchain/openai';
import { DynamicStructuredTool } from '@langchain/core/tools';
import { z } from 'zod';
import * as dotenv from 'dotenv';
import { createPost, getRecentPosts, searchPosts } from './wordpress';

Co importujemy:

  • ChatOpenAI – klasa do komunikacji z modelem AI
  • DynamicStructuredTool – klasa do definiowania narzędzi
  • z – biblioteka Zod do walidacji danych
  • dotenv – wczytuje zmienne z .env
  • {createPost, ...} – nasze funkcje WordPress

import * as dotenv – importuje wszystko jako obiekt „dotenv”
from './wordpress' – z naszego pliku (kropka = bieżący katalog)

Wczytanie zmiennych środowiskowych

dotenv.config();

Ta linia wczytuje zmienne z pliku .env do process.env. Musi być na początku, zanim użyjemy zmiennych.

Konfiguracja modelu AI

const model = new ChatOpenAI({
  modelName: 'bielik-11b-v3.0-instruct@q5_k_m',
  apiKey: 'lm-studio',
  configuration: {
    baseURL: 'http://127.0.0.1:1234/v1',
  },
  temperature: 0.1,
});

Tworzymy instancję modelu AI:

new ChatOpenAI({...})
Tworzymy nowy obiekt klasy ChatOpenAI. new to słowo kluczowe do tworzenia obiektów.

Parametry konfiguracji:
modelName – nazwa modelu w LM Studio
apiKey – klucz API (LM Studio nie wymaga prawdziwego)
baseURL – adres serwera LM Studio
temperature: 0.1 – „kreatywność” modelu (0 = deterministyczny, 1 = losowy)

Czym jest klasa i instancja?

Klasa to „przepis” na obiekt (jak przepis na ciasto).
Instancja to konkretny obiekt stworzony z klasy (jak upieczone ciasto).

ChatOpenAI – klasa (przepis)
new ChatOpenAI({...}) – tworzymy instancję (pieczemy ciasto)
model – zmienna przechowująca naszą instancję

Definicja narzędzi

const tools = [
  new DynamicStructuredTool({
    name: 'get_recent_posts',
    description: 'Pobiera listę ostatnich wpisów z bloga WordPress',
    schema: z.object({
      count: z.number().optional().describe('Liczba wpisów do pobrania (domyślnie 5)'),
    }),
    func: async ({ count }) => {
      return await getRecentPosts(count);
    },
  }),

Co to są narzędzia (tools)?
Narzędzia to funkcje, które model AI może wywoływać. Model „decyduje” kiedy użyć narzędzia na podstawie zapytania użytkownika.

Struktura narzędzia:

name: 'get_recent_posts'
Unikalna nazwa narzędzia. Model używa jej do identyfikacji.

description: '...'
Opis co robi narzędzie. To instrukcja dla modelu AI, model czyta to i decyduje czy użyć tego narzędzia.

schema: z.object({...})
Schemat parametrów używając biblioteki Zod:
– z.object – obiekt z polami
– count: z.number() – pole „count” musi być liczbą
– .optional() – pole jest opcjonalne
– .describe('...') – opis dla modelu AI

func: async ({ count }) => {...}
Funkcja wykonywana gdy model wywoła narzędzie:
– { count } – destrukturyzacja: wyciągamy pole „count” z parametrów
– await getRecentPosts(count) – wywołujemy naszą funkcję z pliku WordPress

Definicja narzędzi – Część 2 i 3

  new DynamicStructuredTool({
    name: 'search_posts',
    description: 'Wyszukuje wpisy na blogu WordPress po słowie kluczowym',
    schema: z.object({
      term: z.string().describe('Szukana fraza lub słowo kluczowe'),
    }),
    func: async ({ term }) => {
      return await searchPosts(term);
    },
  }),
  new DynamicStructuredTool({
    name: 'create_post',
    description: 'Tworzy nowy wpis na blogu WordPress',
    schema: z.object({
      title: z.string().describe('Tytuł wpisu'),
      content: z.string().describe('Treść wpisu w formacie HTML lub tekstowym'),
      status: z.enum(['publish', 'draft']).optional()
        .describe('Status wpisu: publish (opublikowany) lub draft (szkic). Domyślnie draft.'),
    }),
    func: async ({ title, content, status }) => {
      return await createPost(title, content, status);
    },
  }),
];

Narzędzie search_posts:
– Parametr: term: z.string() – tekst do wyszukania
– Wywołuje funkcję searchPosts(term)

Narzędzie create_post:
– Trzy parametry: title, content, status
– z.enum(['publish', 'draft']) – tylko te dwie wartości
– Destrukturyzacja trzech pól: { title, content, status }

Czyli jak widzisz, listę narzędzie dla modelu definiujemy jako tablicę metod.

Mapa funkcji – KLUCZOWE!

const toolFunctions: Record<string, Function> = {
  get_recent_posts: getRecentPosts,
  search_posts: searchPosts,
  create_post: createPost,
};

Dlaczego to jest potrzebne?
W moich testach Model Bielik zwraca nazwę narzędzia jako string (np. „get_recent_posts”).
Musimy przekształcić ten string na prawdziwą funkcję i ją wywołać.

Ta mapa pozwala nam zrobić: toolFunctions['get_recent_posts'] – funkcja getRecentPosts

Record<string, Function> – typ TypeScript: obiekt gdzie klucze to stringi, wartości to funkcje.

Funkcja główna – Część 1

async function main() {
  const prompt = process.argv[2];

  if (!prompt) {
    console.error('Proszę podać prompt jako argument!');
    console.log('Przykład: npm start "Znajdź wpisy o AI"');
    process.exit(1);
  }

  console.log(`Przetwarzam zapytanie: "${prompt}"...\n`);

Wyjaśnienie:

async function main()
Główna funkcja aplikacji. Asynchroniczna, bo będzie czekać na AI.

const prompt = process.argv[2]
process.argv to tablica argumentów z linii komend:
– [0] – ścieżka do node
– [1] – ścieżka do skryptu
– [2] – pierwszy argument użytkownika

Przykład: npm start "Pokaż wpisy"
process.argv[2] = „Pokaż wpisy”

if (!prompt)
Sprawdzamy czy użytkownik podał argument. ! to negacja (nie).

process.exit(1)
Kończy program z kodem błędu 1 (0 = sukces, inne = błąd).

Funkcja główna – Część 2

  try {
    const modelWithTools = model.bindTools(tools);
    
    const result = await modelWithTools.invoke([
      {
        role: 'system',
        content: `Jesteś pomocnym asystentem WordPress. 
Twoim zadaniem jest zarządzanie blogiem użytkownika. 
Możesz tworzyć wpisy, szukać ich i listować.
Zawsze odpowiadaj po polsku.
Jeśli wykonujesz akcję, potwierdź co zrobiłeś.`,
      },
      {
        role: 'user',
        content: prompt,
      },
    ]);

Wyjaśnienie krok po kroku:

try { ... }
Blok try-catch łapie błędy podczas wykonywania.

const modelWithTools = model.bindTools(tools)
„Podpinamy” narzędzia do modelu. Model teraz wie, że może je wywoływać.

const result = await modelWithTools.invoke([...])
Wywołujemy model z tablicą wiadomości:

Wiadomość systemowa (role: 'system’):
Instrukcje dla modelu. Definiują jego zachowanie i osobowość.
Model czyta to przed przetworzeniem zapytania użytkownika.

Wiadomość użytkownika (role: 'user’):
Zapytanie/polecenie od użytkownika (nasze prompt).

Jak działa konwersacja z AI?

AI otrzymuje tablicę wiadomości z różnymi rolami:

  • system – instrukcje systemowe (jak ma się zachowywać)
  • user – wiadomości użytkownika
  • assistant – poprzednie odpowiedzi AI (w historii)

Model przetwarza całą historię i generuje odpowiedź.

Funkcja główna – Część 3

⚠️ BEZ TEGO KODU APLIKACJA NIE BĘDZIE DZIAŁAĆ!
Model Bielik generuje tool_calls, ale LangChain nie wykonywał ich automatycznie.
Musimy ręcznie sprawdzić czy są tool_calls i wykonać prawdziwe funkcje.

    // Sprawdzamy czy model chce użyć narzędzia
    if (result.tool_calls && result.tool_calls.length > 0) {
      console.log('Wykryto wywołanie narzędzia, wykonuję...\n');
      
      const toolCall = result.tool_calls[0];
      const toolName = toolCall.name;
      const toolArgs = toolCall.args;
      
      console.log(`Narzędzie: ${toolName}`);
      console.log(`Parametry:`, toolArgs);
      
      // Wykonaj prawdziwe narzędzie WordPress
      const toolFunction = toolFunctions[toolName];
      if (toolFunction) {
        const toolResult = await toolFunction(...Object.values(toolArgs));
        console.log('\nWynik z WordPress:');
        console.log(toolResult);
        
        // Wygeneruj finalną odpowiedź na podstawie prawdziwego wyniku
        const finalResult = await model.invoke([
          {
            role: 'system',
            content: 'Jesteś pomocnym asystentem WordPress. Odpowiadaj po polsku.',
          },
          {
            role: 'user',
            content: `Użytkownik zapytał: "${prompt}"

Wykonałeś narzędzie ${toolName} i otrzymałeś wynik:
${toolResult}

Podaj użytkownikowi przyjazną odpowiedź na podstawie tego wyniku.`,
          },
        ]);
        
        console.log('\nOdpowiedź AI:');
        console.log(finalResult.content);
      } else {
        console.log('Nie znaleziono funkcji dla narzędzia:', toolName);
      }
    } else {
      // Jeśli nie było wywołań narzędzi, zwróć normalną odpowiedź
      console.log('\nOdpowiedź AI:');
      console.log(result.content);
    }

Krok po kroku co się dzieje:

1. if (result.tool_calls && result.tool_calls.length > 0)
Sprawdzamy czy model zwrócił jakieś wywołania narzędzi

2. const toolCall = result.tool_calls[0]
Bierzemy pierwsze wywołanie (dla uproszczenia obsługujemy jedno)

3. const toolName = toolCall.name
Nazwa narzędzia, np. „get_recent_posts”

4. const toolArgs = toolCall.args
Parametry, np. {count: 5}

5. const toolFunction = toolFunctions[toolName]
Znajdujemy funkcję w naszej mapie

6. await toolFunction(...Object.values(toolArgs))
Wykonujemy prawdziwą funkcję WordPress:
– Object.values(toolArgs) -> wyciąga wartości z obiektu do tablicy
– ... (spread) -> rozpakuje tablicę na argumenty
– Przykład: {count: 5} -> [5] -> getRecentPosts(5)

7. Drugie wywołanie modelu
Wysyłamy do modelu prawdziwy wynik z WordPress
Model generuje przyjazną odpowiedź dla użytkownika

Dlaczego dwa wywołania?
– Pierwsze: Model decyduje KTÓRE narzędzie użyć
– My: Wykonujemy PRAWDZIWE narzędzie
– Drugie: Model tworzy PRZYJAZNĄ odpowiedź z prawdziwych danych

Obsługa błędów i uruchomienie

  } catch (error) {
    console.error('Wystąpił błąd:', error);
  }
}

main();

catch (error) – jeśli coś pójdzie nie tak w try, wyświetl błąd

main(); – wywołujemy funkcję główną, startujemy aplikację

TESTY wersji pierwszej, z wywołaniem jednorazowym, w części drugiej zrobimy chata w konsoli a w trzeciej webową aplikację.

uruchamiamy program, i w parametrze przekazuje pytanie do modelu

npm start "Pokaż ostatnie wpisy" 

Widać wywołanie tools przez model:

Przetwarzam zapytanie: "Pokaż ostatnie wpisy"...

Wykryto wywołanie narzędzia, wykonuję...

Narzędzie: get_recent_posts
Parametry: { count: 5 }

Wynik z WordPress:
- [1346] Programowanie od zera: Lekcja 5: Program zyskuje pamięć trwałą (Pliki, JSON i Typy Danych) (2026-01-03T21:46:26)
- [1308] SQL od Zera, cz. 13: Podróże w czasie czyli analiza trendów za pomocą LAG i LEAD (2025-12-21T23:02:39)
- [1302] Garść info: kursy programowania i SQL, moja aplikacja niedługo dostępna, uczę się TypeScripta (2025-12-19T23:25:05)
- [1289] Kurs programowania od zera, lekcja: 4B: C# Dogania Pythona (Klasy, Obiekty i Listy Rekordów) (2025-12-14T22:13:05)
- [1279] SQL od Zera, cz. 12: Świat funkcji okien na grubo – suma i średnia krocząca (2025-12-12T22:47:50)

Wynik z wordpresa trafia do modelu, a model zwraca odpowiedź wykorzystując ten kontekst:

Odpowiedź AI:
Oto najnowsze wpisy z bloga, które mogą Cię zainteresować:

1. **Programowanie od zera: Lekcja 5: Program zyskuje pamięć trwałą (Pliki, JSON i Typy Danych)**
   Data publikacji: 3 stycznia 2026 r.
   W tej lekcji dowiesz się, jak przechowywać dane w plikach oraz pracować z formatem JSON i typami danych.

2. **SQL od Zera, cz. 13: Podróże w czasie czyli analiza trendów za pomocą LAG i LEAD**

   Data publikacji: 21 grudnia 2025 r.
   Naucz się korzystać z funkcji `LAG` i `LEAD`, aby analizować dane w czasie, np. trendy sprzedaży lub zmiany cen.

3. **Garść info: kursy programowania i SQL, moja aplikacja niedługo dostępna, uczę się TypeScripta**
   Data publikacji: 19 grudnia 2025 r.
   Aktualizacja na temat nowych kursów online oraz postępów w rozwoju aplikacji do nauki programowania i SQL.

4. **Kurs programowania od zera, lekcja: 4B: C# Dogania Pythona (Klasy, Obiekty i Listy Rekordów)**
   Data publikacji: 14 grudnia 2025 r.
   Porównanie języków Python i C# w kontekście programowania obiektowego oraz tworzenia klas i list rekordów.

5. **SQL od Zera, cz. 12: Świat funkcji okien na grubo — suma i średnia krocząca**     
   Data publikacji: 12 grudnia 2025 r.
   Praktyczne zastosowanie funkcji okien (window functions) do obliczania sumy i średniej kroczącej w bazach danych.

Mam nadzieję, że znajdziesz coś dla siebie!

i Całość poniżej

PS E:\projekty\kurs JS TS\bielik-wp> npm start "Pokaż ostatnie wpisy"

> bielik-wp@1.0.0 start
> tsx src/index.ts Pokaż ostatnie wpisy

[dotenv@17.2.3] injecting env (3) from .env -- tip: ⚙️  write to custom object with { pprocessEnv: myObject }
[dotenv@17.2.3] injecting env (0) from .env -- tip: ⚙️  write to custom object with { pprocessEnv: myObject }
Przetwarzam zapytanie: "Pokaż ostatnie wpisy"...

Wykryto wywołanie narzędzia, wykonuję...

Narzędzie: get_recent_posts
Parametry: { count: 5 }

Wynik z WordPress:
- [1346] Programowanie od zera: Lekcja 5: Program zyskuje pamięć trwałą (Pliki, JSON i Typy Danych) (2026-01-03T21:46:26)
- [1308] SQL od Zera, cz. 13: Podróże w czasie czyli analiza trendów za pomocą LAG i LEAD (2025-12-21T23:02:39)
- [1302] Garść info: kursy programowania i SQL, moja aplikacja niedługo dostępna, uczę się TypeScripta (2025-12-19T23:25:05)
- [1289] Kurs programowania od zera, lekcja: 4B: C# Dogania Pythona (Klasy, Obiekty i Listy Rekordów) (2025-12-14T22:13:05)
- [1279] SQL od Zera, cz. 12: Świat funkcji okien na grubo – suma i średnia krocząca (2025-12-12T22:47:50)

Odpowiedź AI:
Oto najnowsze wpisy z bloga, które mogą Cię zainteresować:

1. **Programowanie od zera: Lekcja 5: Program zyskuje pamięć trwałą (Pliki, JSON i Typy Danych)**
   Data publikacji: 3 stycznia 2026 r.
   W tej lekcji dowiesz się, jak przechowywać dane w plikach oraz pracować z formatem JSON i typami danych.

2. **SQL od Zera, cz. 13: Podróże w czasie czyli analiza trendów za pomocą LAG i LEAD**

   Data publikacji: 21 grudnia 2025 r.
   Naucz się korzystać z funkcji `LAG` i `LEAD`, aby analizować dane w czasie, np. trendy sprzedaży lub zmiany cen.

3. **Garść info: kursy programowania i SQL, moja aplikacja niedługo dostępna, uczę się TypeScripta**
   Data publikacji: 19 grudnia 2025 r.
   Aktualizacja na temat nowych kursów online oraz postępów w rozwoju aplikacji do nauki programowania i SQL.

4. **Kurs programowania od zera, lekcja: 4B: C# Dogania Pythona (Klasy, Obiekty i Listy Rekordów)**
   Data publikacji: 14 grudnia 2025 r.
   Porównanie języków Python i C# w kontekście programowania obiektowego oraz tworzenia klas i list rekordów.

5. **SQL od Zera, cz. 12: Świat funkcji okien na grubo — suma i średnia krocząca**     
   Data publikacji: 12 grudnia 2025 r.
   Praktyczne zastosowanie funkcji okien (window functions) do obliczania sumy i średniej kroczącej w bazach danych.

Mam nadzieję, że znajdziesz coś dla siebie!
PS E:\projekty\kurs JS TS\bielik-wp>

WSZYSTKO DZIAŁA!

Zachęcam do eksperymentów

0 komentarzy

Wyślij komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

Share This

Share this post with your friends!