/
Ao
/
1c_AI_Spec
Обзор
Документация
Войти
/
Ao
/
1c_AI_Spec
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
openspec-memory-server/graph.go
177 строк
5 KB
Максимчук Александр Олегович
mcp surreal
03 июл 2026, 16:56
03 июл 2026, 16:56
f1f7f32
Код
Авторство
О чём код?
package main import ( "context" "fmt" "time" surrealdb "github.com/surrealdb/surrealdb.go" ) type СвязьГрафа struct { ID string `json:"id"` SourceID string `json:"source_id"` TargetID string `json:"target_id"` RelationType string `json:"relation_type"` Weight float32 `json:"weight"` Metadata map[string]any `json:"metadata,omitempty"` CreatedAt time.Time `json:"created_at"` } type УзелГрафа struct { ID string `json:"id"` ChangeName string `json:"change_name"` Language string `json:"language"` TaskType string `json:"task_type"` } type Граф struct { Узлы []УзелГрафа `json:"nodes"` Рёбра []СвязьГрафа `json:"edges"` } func ПостроитьСвязи(ctx context.Context, новыйДиалог Диалог, все []Диалог) ([]СвязьГрафа, error) { var связи []СвязьГрафа for _, существующий := range все { if существующий.ID == новыйДиалог.ID { continue } score := ВекторноеСходство(новыйДиалог.Keywords, существующий.Keywords) if score > 0.3 { связи = append(связи, СвязьГрафа{ SourceID: существующий.ID, TargetID: новыйДиалог.ID, RelationType: "похожий_диалог", Weight: score, CreatedAt: time.Now(), }) } if естьОбщиеЯзыки(новыйДиалог.Language, существующий.Language) { связи = append(связи, СвязьГрафа{ SourceID: существующий.ID, TargetID: новыйДиалог.ID, RelationType: "общий_язык", Weight: 0.3, CreatedAt: time.Now(), }) } if естьОбщиеТипыЗадач(новыйДиалог.TaskType, существующий.TaskType) { связи = append(связи, СвязьГрафа{ SourceID: существующий.ID, TargetID: новыйДиалог.ID, RelationType: "смежная_задача", Weight: 0.4, CreatedAt: time.Now(), }) } } for _, связь := range связи { if err := сохранитьСвязь(ctx, связь); err != nil { return nil, err } } return связи, nil } func сохранитьСвязь(ctx context.Context, связь СвязьГрафа) error { query := `RELATE $from ->relations-> $to SET relation_type = $relation_type, weight = $weight, metadata = $metadata, created_at = $created_at` vars := map[string]any{ "from": связь.SourceID, "to": связь.TargetID, "relation_type": связь.RelationType, "weight": связь.Weight, "metadata": связь.Metadata, "created_at": связь.CreatedAt, } if _, err := surrealdb.Query[any](ctx, SurrealDB, query, vars); err != nil { return fmt.Errorf("failed to save relation: %w", err) } return nil } func ПолучитьГраф(ctx context.Context, dialogueID string, depth int) (*Граф, error) { query := `SELECT id, in, out, relation_type, weight, metadata FROM relations WHERE in = $dialogue_id OR out = $dialogue_id AND weight >= $min_weight LIMIT $limit` vars := map[string]any{ "dialogue_id": dialogueID, "min_weight": float32(0.2), "limit": 100, } result, err := surrealdb.Query[any](ctx, SurrealDB, query, vars) if err != nil { return nil, fmt.Errorf("graph query failed: %w", err) } graf := &Граф{ Узлы: []УзелГрафа{}, Рёбра: []СвязьГрафа{}, } if result != nil && len(*result) > 0 { for _, r := range *result { if r.Error != nil { continue } edge := СвязьГрафа{ ID: fmt.Sprintf("%v", r.Result), SourceID: fmt.Sprintf("%v", r.Result), TargetID: fmt.Sprintf("%v", r.Result), RelationType: fmt.Sprintf("%v", r.Result), Weight: float32(0), } graf.Рёбра = append(graf.Рёбра, edge) } } return graf, nil } func ВекторноеСходство(а, б []string) float32 { if len(а) == 0 || len(б) == 0 { return 0 } множествоА := make(map[string]bool) for _, к := range а { множествоА[к] = true } совпадения := 0 for _, к := range б { if множествоА[к] { совпадения++ } } total := len(а) + len(б) - совпадения if total == 0 { return 0 } return float32(совпадения) / float32(total) } func естьОбщиеЯзыки(а, б string) bool { return а == б } func естьОбщиеТипыЗадач(а, б string) bool { return а == б }