• نبذة عن Milvus
  • ابدأ الآن
  • المفاهيم
  • دليل المستخدم
  • استيراد البيانات
  • أدوات الذكاء الاصطناعي
  • دليل الإدارة
  • الأدوات
  • عمليات التكامل
  • الدروس التعليمية
  • الأسئلة الشائعة
  • API Reference

بناء ذاكرة طويلة الأمد للوكلاء باستخدام EverOS وMilvus

EverOS هو نظام ذاكرة يعتمد على Markdown في المقام الأول مخصص لوكلاء الذكاء الاصطناعي. فهو يستخرج الذكريات الدائمة من المحادثات، ويحتفظ بـ Markdown كمصدر موثوق للمعلومات، ويبني فهرسًا مشتقًا قابلًا للبحث.

في هذا البرنامج التعليمي، سنقوم بإنشاء مساعد مشروع يتذكر قرارات الإصدار عبر محادثات منفصلة. سنضيف محادثات حول إطلاق مشروع Atlas إلى جانب محادثات غير ذات صلة حول مشاريع أخرى. سيستخدم EverOS نموذج لغة كبير (LLM) لاستخراج الذكريات، بينما يقوم Milvus بتخزين مؤشرات BM25 والمتجهات المستخدمة في البحث الهجين.

Conversations
      |
      v
EverOS + LLM ------> Markdown memory files
      |
      | embedding model
      v
Milvus ------> BM25 + vector hybrid search

يختلف دور كل من نموذج اللغة الكبير (LLM) ونموذج التضمين (embedding model). يقوم نموذج اللغة الكبير بتحويل المحادثة إلى ذكريات منظمة. أما نموذج التضمين فيقوم بتحويل تلك الذكريات واستعلامات البحث اللاحقة إلى متجهات. لا يتطلب البحث الهجين الأساسي في هذا البرنامج التعليمي نموذجًا لإعادة الترتيب.

المتطلبات الأساسية

تحتاج إلى:

يتصل هذا البرنامج التعليمي بخادم Milvus على العنوان http://localhost:19530. كما يدعم EverOS خدمة Zilliz Cloud من خلال نفس إعدادات URI ورمز التوثيق. وتتوقع الخلفية البرمجية لـ Milvus وجود نقطة نهاية عن بُعد ولا تقبل مسار ملف Milvus Lite.

تثبيت EverOS

قم بإنشاء مشروع محلي وتثبيت EverOS مع تبعيات Milvus الاختيارية:

mkdir everos-milvus-demo
cd everos-milvus-demo

uv init --bare --python 3.12
uv add "everos[milvus]"

لا يحدد الأمر إصدارًا عن قصد، لذا فإن التثبيت الجديد سيحدد أحدث إصدار متوافق من EverOS.

تهيئة جذر ذاكرة منفصل للبرنامج التعليمي:

export EVEROS_ROOT="$PWD/everos-data"
uv run everos init --root "$EVEROS_ROOT"

يقوم EverOS بإنشاء everos.toml و ome.toml ضمن هذا الدليل. كما سيقوم بكتابة الذاكرات المستخرجة هنا.

تكوين OpenAI و Milvus

قم بتعيين مفتاح واجهة برمجة تطبيقات OpenAI وتهيئة EverOS من خلال متغيرات البيئة:

export OPENAI_API_KEY="YOUR_OPENAI_API_KEY"
export MILVUS_URI="http://localhost:19530"

export EVEROS_INDEX__BACKEND="milvus"
export EVEROS_MILVUS__URI="$MILVUS_URI"
export EVEROS_MILVUS__COLLECTION_PREFIX="everos_bootcamp"

export EVEROS_LLM__MODEL="gpt-5.4-mini"
export EVEROS_LLM__API_KEY="$OPENAI_API_KEY"
export EVEROS_LLM__BASE_URL="https://api.openai.com/v1"

export EVEROS_EMBEDDING__MODEL="text-embedding-3-small"
export EVEROS_EMBEDDING__API_KEY="$OPENAI_API_KEY"
export EVEROS_EMBEDDING__BASE_URL="https://api.openai.com/v1"
export EVEROS_EMBEDDING__DIMENSIONS="1024"

export EVEROS_MEMORIZE__MODE="chat"

يستخدم EverOS OpenAI لكل من استخراج الذاكرة والتضمينات. يُرجع text-embedding-3-small أبعاد 1536 افتراضيًا، لكن EverOS يُرسل قيمة dimensions المُهيأة إلى OpenAI. يطلب هذا البرنامج التعليمي أبعاد 1024 لتتوافق مع مخططات Milvus التي يديرها EverOS.

يُحافظ وضع الذاكرة chat على تركيز هذا المثال على ذاكرات المستخدمين. يدير EverOS مجموعات Milvus ومخططاتها، لذا لا تحتاج إلى إنشائها بنفسك.

بدء تشغيل EverOS

ابدأ تشغيل خادم HTTP الخاص بـ EverOS:

uv run everos server start --root "$EVEROS_ROOT"

اترك هذا المحطة الطرفية مفتوحة. يتصل EverOS بـ Milvus ويُنشئ سبع مجموعات ذات فهارس مشتقة بالبادئة المُعدة مسبقًا أثناء بدء التشغيل.

افتح محطة طرفية أخرى في نفس دليل المشروع وتحقق من الخدمة:

curl http://127.0.0.1:8000/health

إخراج مرجعي:

{
  "status": "ok",
  "version": "1.3.0",
  "capabilities": {
    "llm": true,
    "embed": true,
    "rerank": false,
    "multimodal_llm": false,
    "parser": true
  },
  "cascade": {
    "healthy": true,
    "pending": 0
  }
}

تحتوي الاستجابة على حقول حالة إضافية. القيم المهمة لهذا البرنامج التعليمي هي status: "ok" و llm: true و embed: true و cascade.healthy: true.

إضافة محادثات المشروع

يرسل برنامج Python التالي عشر محادثات مستقلة إلى EverOS. يحتوي Atlas على مناقشات منفصلة حول التشغيل والتراجع. توفر ثماني محادثات حول مشاريع أخرى عوامل تشتيت الانتباه بحيث يتعين على البحث اللاحق تحديد ذكريات المشروع الصحيحة.

احفظ الكود التالي باسم add_memories.py:

import json
import time
from urllib.request import Request, urlopen


API_URL = "http://127.0.0.1:8000/api/v2/memory"
NOW = int(time.time() * 1000)

conversations = [
    (
        "atlas-release",
        [
            {
                "sender_id": "maya",
                "sender_name": "Maya",
                "role": "user",
                "timestamp": NOW,
                "content": (
                    "For Project Atlas, we decided to launch with a 10% canary "
                    "on September 30. Promote to all users only after the checkout "
                    "error rate stays below 1% for 30 minutes."
                ),
            },
            {
                "sender_id": "assistant",
                "role": "assistant",
                "timestamp": NOW + 1_000,
                "content": (
                    "Understood. I will remember the Atlas launch date, canary "
                    "percentage, and promotion gate."
                ),
            },
        ],
    ),
    (
        "atlas-rollback",
        [
            {
                "sender_id": "maya",
                "sender_name": "Maya",
                "role": "user",
                "timestamp": NOW + 10_000,
                "content": (
                    "The Atlas rollback owner is Priya. Roll back immediately if "
                    "checkout errors exceed 2% for five minutes, and keep the "
                    "previous container image available for 24 hours."
                ),
            },
            {
                "sender_id": "assistant",
                "role": "assistant",
                "timestamp": NOW + 11_000,
                "content": (
                    "Got it. Priya owns rollback, with the 2% five-minute trigger "
                    "and a 24-hour image retention window."
                ),
            },
        ],
    ),
    (
        "orion-pricing",
        [
            {
                "sender_id": "maya",
                "sender_name": "Maya",
                "role": "user",
                "timestamp": NOW + 20_000,
                "content": (
                    "Project Orion will test annual billing with the education "
                    "segment. The pricing review is scheduled for October 12."
                ),
            },
            {
                "sender_id": "assistant",
                "role": "assistant",
                "timestamp": NOW + 21_000,
                "content": (
                    "I will remember Orion's annual billing experiment and October "
                    "pricing review."
                ),
            },
        ],
    ),
    (
        "vega-mobile",
        [
            {
                "sender_id": "maya",
                "sender_name": "Maya",
                "role": "user",
                "timestamp": NOW + 30_000,
                "content": (
                    "For Project Vega, the mobile team chose offline drafts as the "
                    "next milestone. Elena will review the interaction design on "
                    "October 18."
                ),
            },
            {
                "sender_id": "assistant",
                "role": "assistant",
                "timestamp": NOW + 31_000,
                "content": (
                    "Noted. Vega's next milestone is offline drafts, followed by "
                    "Elena's design review."
                ),
            },
        ],
    ),
    (
        "nova-warehouse",
        [
            {
                "sender_id": "maya",
                "sender_name": "Maya",
                "role": "user",
                "timestamp": NOW + 40_000,
                "content": (
                    "Project Nova will migrate the analytics warehouse to Iceberg. "
                    "Marcus owns the checksum rehearsal scheduled for October 22."
                ),
            },
            {
                "sender_id": "assistant",
                "role": "assistant",
                "timestamp": NOW + 41_000,
                "content": (
                    "I will remember Nova's warehouse migration and Marcus's "
                    "checksum rehearsal."
                ),
            },
        ],
    ),
    (
        "helios-support",
        [
            {
                "sender_id": "maya",
                "sender_name": "Maya",
                "role": "user",
                "timestamp": NOW + 50_000,
                "content": (
                    "Project Helios needs weekend support coverage for the APAC "
                    "region. Imani will publish the rotation schedule on November 1."
                ),
            },
            {
                "sender_id": "assistant",
                "role": "assistant",
                "timestamp": NOW + 51_000,
                "content": (
                    "Noted. Helios needs APAC weekend coverage, and Imani owns the "
                    "rotation schedule."
                ),
            },
        ],
    ),
    (
        "luna-onboarding",
        [
            {
                "sender_id": "maya",
                "sender_name": "Maya",
                "role": "user",
                "timestamp": NOW + 60_000,
                "content": (
                    "Project Luna will replace the onboarding tour with a checklist. "
                    "The localized copy is due from the content team on October 25."
                ),
            },
            {
                "sender_id": "assistant",
                "role": "assistant",
                "timestamp": NOW + 61_000,
                "content": (
                    "I will remember Luna's checklist approach and the localization "
                    "deadline."
                ),
            },
        ],
    ),
    (
        "aurora-observability",
        [
            {
                "sender_id": "maya",
                "sender_name": "Maya",
                "role": "user",
                "timestamp": NOW + 70_000,
                "content": (
                    "Project Aurora will retain detailed telemetry for 30 days. "
                    "The operations team should alert after three consecutive "
                    "heartbeat misses."
                ),
            },
            {
                "sender_id": "assistant",
                "role": "assistant",
                "timestamp": NOW + 71_000,
                "content": (
                    "Understood. Aurora keeps 30 days of telemetry and alerts after "
                    "three missed heartbeats."
                ),
            },
        ],
    ),
    (
        "comet-invoices",
        [
            {
                "sender_id": "maya",
                "sender_name": "Maya",
                "role": "user",
                "timestamp": NOW + 80_000,
                "content": (
                    "Project Comet will add downloadable invoice PDFs for enterprise "
                    "accounts. Finance will approve the tax-field layout on October 28."
                ),
            },
            {
                "sender_id": "assistant",
                "role": "assistant",
                "timestamp": NOW + 81_000,
                "content": (
                    "Noted. Comet covers enterprise invoice PDFs and an October tax "
                    "layout review."
                ),
            },
        ],
    ),
    (
        "solstice-research",
        [
            {
                "sender_id": "maya",
                "sender_name": "Maya",
                "role": "user",
                "timestamp": NOW + 90_000,
                "content": (
                    "Project Solstice is prototyping voice notes for field researchers. "
                    "The research team will interview 12 participants in November."
                ),
            },
            {
                "sender_id": "assistant",
                "role": "assistant",
                "timestamp": NOW + 91_000,
                "content": (
                    "I will remember Solstice's voice-note prototype and the planned "
                    "participant interviews."
                ),
            },
        ],
    ),
]


def post(path, payload):
    request = Request(
        f"{API_URL}/{path}",
        data=json.dumps(payload).encode(),
        headers={"Content-Type": "application/json"},
        method="POST",
    )
    with urlopen(request, timeout=300) as response:
        return json.load(response)["data"]


for session_id, messages in conversations:
    added = post(
        "add",
        {
            "session_id": session_id,
            "app_id": "project-assistant",
            "project_id": "launch-planning",
            "messages": messages,
            "defer_extraction": True,
        },
    )
    flushed = post(
        "flush",
        {
            "session_id": session_id,
            "app_id": "project-assistant",
            "project_id": "launch-planning",
        },
    )
    print(f"{session_id}: {added['status']} -> {flushed['status']}")

قم بتشغيله من دليل المشروع:

uv run python add_memories.py

نموذج الإخراج:

atlas-release: accumulated -> extracted
atlas-rollback: accumulated -> extracted
orion-pricing: accumulated -> extracted
vega-mobile: accumulated -> extracted
nova-warehouse: accumulated -> extracted
helios-support: accumulated -> extracted
luna-onboarding: accumulated -> extracted
aurora-observability: accumulated -> extracted
comet-invoices: accumulated -> extracted
solstice-research: accumulated -> extracted

يؤدي تعيين defer_extraction إلى true إلى تخزين كل محادثة في المخزن المؤقت الدائم دون مطالبة نموذج اللغة الكبير (LLM) باكتشاف الحدود. ويشير استدعاء /flush التالي إلى نهاية تلك الجلسة ويؤدي إلى عملية استخراج واحدة. ثم يقوم EverOS بكتابة الحلقة المستخرجة إلى Markdown وتضمينها بشكل غير متزامن في فهرس Milvus.

فحص ذاكرة Markdown

يتم تخزين ملف الحلقة الذي تم إنشاؤه ضمن نطاقات التطبيق والمشروع والمستخدم:

find "$EVEROS_ROOT/project-assistant/launch-planning/users/maya/episodes" \
  -type f -name "*.md"

إخراج مرجعي (يعكس تاريخ اسم الملف وقت تشغيل المثال):

everos-data/project-assistant/launch-planning/users/maya/episodes/episode-2026-09-08.md

افتح الملف لرؤية الذكريات التي استخرجها نموذج اللغة الكبير (LLM). يبدو مقتطف مختصر كما يلي:

## ep_20260908_00000001

**owner_id**: maya
**session_id**: atlas-release
**sender_ids**: [maya, assistant]

### Subject
Maya's Project Atlas Launch Decision: September 30 Canary and Promotion Criteria

### Content
Maya decided that Project Atlas would launch with a 10% canary on September 30.
The promotion to all users would occur only after the checkout error rate remained
below 1% for 30 minutes.

قد تختلف الصياغة الدقيقة والمعرفات والطوابع الزمنية لأن الذاكرة يتم استخراجها بواسطة LLM. تظل ملفات Markdown الأصلية هي المصدر الموثوق الدائم؛ ويمكن إعادة بناء فهرس Milvus منها.

البحث في الذكريات

استخدم البحث المختلط لتحديد ما يجب تذكره قبل إطلاق Atlas. احفظ الكود التالي باسم search_memories.py:

import json
import time
from urllib.request import Request, urlopen


URL = "http://127.0.0.1:8000/api/v2/memory/search"
payload = {
    "user_id": "maya",
    "app_id": "project-assistant",
    "project_id": "launch-planning",
    "query": "What should I remember before Atlas goes live?",
    "method": "hybrid",
    "top_k": 4,
}


def search():
    request = Request(
        URL,
        data=json.dumps(payload).encode(),
        headers={"Content-Type": "application/json"},
        method="POST",
    )
    with urlopen(request, timeout=300) as response:
        return json.load(response)["data"]["episodes"]


expected_sessions = {"atlas-release", "atlas-rollback"}

for _ in range(30):
    episodes = search()
    top_results = episodes[:2]
    if {episode["session_id"] for episode in top_results} == expected_sessions:
        break
    time.sleep(2)
else:
    raise RuntimeError("The expected Atlas memories were not indexed in time")

for rank, episode in enumerate(top_results, start=1):
    print(f"{rank}. {episode['session_id']} | score={episode['score']:.3f}")
    print(f"   {episode['subject']}")

قم بتشغيل البحث:

uv run python search_memories.py

نتائج مرجعية (قد تختلف الدرجات والصياغة):

1. atlas-release | score=0.492
   Project Atlas Launch Plan: 10% Canary Rollout on September 30 with Error Rate Gate
2. atlas-rollback | score=0.400
   Atlas Rollback Plan Details: Priya as Owner, 2% Error Trigger, 24-Hour Image Retention

يتم عرض محادثتي Atlas قبل المحادثات الثماني غير ذات الصلة. يرسل EverOS الاستعلام إلى نقطة نهاية التضمين في OpenAI، ويطلب من Milvus تقديم مرشحات BM25 والمتجهات ضمن نطاق تطبيق Maya والمشروع، ثم يدمج قائمتي النتائج.

افحص مجموعات Milvus

ينشئ EverOS مجموعة واحدة لكل نوع من أنواع الذاكرة المشتقة المدعومة. استخدم MilvusClient لإدراج عدد الصفوف لكل منها:

import os

from pymilvus import MilvusClient


prefix = "everos_bootcamp"
client = MilvusClient(uri=os.environ.get("MILVUS_URI", "http://localhost:19530"))

memory_kinds = [
    "agent_case",
    "agent_skill",
    "atomic_fact",
    "episode",
    "foresight",
    "knowledge_topic",
    "user_profile",
]

for kind in memory_kinds:
    name = f"{prefix}_{kind}"
    if client.has_collection(collection_name=name):
        result = client.query(
            collection_name=name,
            filter="",
            output_fields=["count(*)"],
        )
        print(f"{kind}: {result[0]['count(*)']} rows")

client.close()

راجع مخرجات التشغيل الذي تم التحقق من صحته:

agent_case: 0 rows
agent_skill: 0 rows
atomic_fact: 50 rows
episode: 10 rows
foresight: 0 rows
knowledge_topic: 0 rows
user_profile: 1 rows

قد يختلف العدد الدقيق للحقائق الذرية باختلاف مخرجات LLM. تتوافق الصفوف العشرة الخاصة بالحلقات مع المحادثات العشر التي تم مسحها. تتوفر المجموعات الأخرى لأوضاع الذاكرة وميزات EverOS التي لا يستخدمها هذا المثال المركّز.

استخدام نشر Milvus آخر

لاستخدام نقطة نهاية خادم Milvus أخرى أو Zilliz Cloud، قم بتحديث EVEROS_MILVUS__URI. قم بتعيين EVEROS_MILVUS__TOKEN عندما تتطلب نقطة النهاية المصادقة. يبقى كود الاستيعاب والبحث دون تغيير.

الخلاصة

من خلال الجمع بين EverOS و Milvus، يمكنك تحويل المحادثات إلى ذكريات دائمة واسترجاعها من خلال الكلمات المفتاحية والإشارات الدلالية. يمكنك تكييف النمط نفسه لمنح المساعدات والتطبيقات الوكيلة الأخرى ذاكرة طويلة الأمد لمستخدميك ومشاريعك وسير عملك.

ترجمة بواسطةDeepL

جرب Managed Milvus مجاناً

Zilliz Cloud خالي من المتاعب، ويعمل بواسطة Milvus ويعمل بسرعة 10 أضعاف.

ابدأ
التعليقات

هل كانت هذه الصفحة مفيدة؟