Skip to content

Commit 7822d94

Browse files
authored
chore(p2p): single-node when sharing federated instance (#3354)
* chore(p2p): single-node when sharing federated instance Signed-off-by: Ettore Di Giacinto <[email protected]> * chore: refactor out and extract into functions Signed-off-by: Ettore Di Giacinto <[email protected]> --------- Signed-off-by: Ettore Di Giacinto <[email protected]>
1 parent b510352 commit 7822d94

File tree

2 files changed

+84
-45
lines changed

2 files changed

+84
-45
lines changed

core/cli/api/p2p.go

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package cli_api
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"net"
7+
"os"
8+
"strings"
9+
10+
"github.com/mudler/LocalAI/core/p2p"
11+
"github.com/mudler/edgevpn/pkg/node"
12+
13+
"github.com/rs/zerolog/log"
14+
)
15+
16+
func StartP2PStack(ctx context.Context, address, token, networkID string, federated bool) error {
17+
var n *node.Node
18+
// Here we are avoiding creating multiple nodes:
19+
// - if the federated mode is enabled, we create a federated node and expose a service
20+
// - exposing a service creates a node with specific options, and we don't want to create another node
21+
22+
// If the federated mode is enabled, we expose a service to the local instance running
23+
// at r.Address
24+
if federated {
25+
_, port, err := net.SplitHostPort(address)
26+
if err != nil {
27+
return err
28+
}
29+
30+
// Here a new node is created and started
31+
// and a service is exposed by the node
32+
node, err := p2p.ExposeService(ctx, "localhost", port, token, p2p.NetworkID(networkID, p2p.FederatedID))
33+
if err != nil {
34+
return err
35+
}
36+
37+
if err := p2p.ServiceDiscoverer(ctx, node, token, p2p.NetworkID(networkID, p2p.FederatedID), nil, false); err != nil {
38+
return err
39+
}
40+
41+
n = node
42+
}
43+
44+
// If the p2p mode is enabled, we start the service discovery
45+
if token != "" {
46+
// If a node wasn't created previously, create it
47+
if n == nil {
48+
node, err := p2p.NewNode(token)
49+
if err != nil {
50+
return err
51+
}
52+
err = node.Start(ctx)
53+
if err != nil {
54+
return fmt.Errorf("starting new node: %w", err)
55+
}
56+
n = node
57+
}
58+
59+
// Attach a ServiceDiscoverer to the p2p node
60+
log.Info().Msg("Starting P2P server discovery...")
61+
if err := p2p.ServiceDiscoverer(ctx, n, token, p2p.NetworkID(networkID, p2p.WorkerID), func(serviceID string, node p2p.NodeData) {
62+
var tunnelAddresses []string
63+
for _, v := range p2p.GetAvailableNodes(p2p.NetworkID(networkID, p2p.WorkerID)) {
64+
if v.IsOnline() {
65+
tunnelAddresses = append(tunnelAddresses, v.TunnelAddress)
66+
} else {
67+
log.Info().Msgf("Node %s is offline", v.ID)
68+
}
69+
}
70+
tunnelEnvVar := strings.Join(tunnelAddresses, ",")
71+
72+
os.Setenv("LLAMACPP_GRPC_SERVERS", tunnelEnvVar)
73+
log.Debug().Msgf("setting LLAMACPP_GRPC_SERVERS to %s", tunnelEnvVar)
74+
}, true); err != nil {
75+
return err
76+
}
77+
}
78+
79+
return nil
80+
}

core/cli/run.go

Lines changed: 4 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,10 @@ package cli
33
import (
44
"context"
55
"fmt"
6-
"net"
7-
"os"
86
"strings"
97
"time"
108

9+
cli_api "github.com/mudler/LocalAI/core/cli/api"
1110
cliContext "github.com/mudler/LocalAI/core/cli/context"
1211
"github.com/mudler/LocalAI/core/config"
1312
"github.com/mudler/LocalAI/core/http"
@@ -115,52 +114,12 @@ func (r *RunCMD) Run(ctx *cliContext.Context) error {
115114
fmt.Printf("export TOKEN=\"%s\"\nlocal-ai worker p2p-llama-cpp-rpc\n", token)
116115
}
117116
opts = append(opts, config.WithP2PToken(token))
118-
119-
node, err := p2p.NewNode(token)
120-
if err != nil {
121-
return err
122-
}
123-
nodeContext := context.Background()
124-
125-
err = node.Start(nodeContext)
126-
if err != nil {
127-
return fmt.Errorf("starting new node: %w", err)
128-
}
129-
130-
log.Info().Msg("Starting P2P server discovery...")
131-
if err := p2p.ServiceDiscoverer(nodeContext, node, token, p2p.NetworkID(r.Peer2PeerNetworkID, p2p.WorkerID), func(serviceID string, node p2p.NodeData) {
132-
var tunnelAddresses []string
133-
for _, v := range p2p.GetAvailableNodes(p2p.NetworkID(r.Peer2PeerNetworkID, p2p.WorkerID)) {
134-
if v.IsOnline() {
135-
tunnelAddresses = append(tunnelAddresses, v.TunnelAddress)
136-
} else {
137-
log.Info().Msgf("Node %s is offline", v.ID)
138-
}
139-
}
140-
tunnelEnvVar := strings.Join(tunnelAddresses, ",")
141-
142-
os.Setenv("LLAMACPP_GRPC_SERVERS", tunnelEnvVar)
143-
log.Debug().Msgf("setting LLAMACPP_GRPC_SERVERS to %s", tunnelEnvVar)
144-
}, true); err != nil {
145-
return err
146-
}
147117
}
148118

149-
if r.Federated {
150-
_, port, err := net.SplitHostPort(r.Address)
151-
if err != nil {
152-
return err
153-
}
154-
fedCtx := context.Background()
155-
156-
node, err := p2p.ExposeService(fedCtx, "localhost", port, token, p2p.NetworkID(r.Peer2PeerNetworkID, p2p.FederatedID))
157-
if err != nil {
158-
return err
159-
}
119+
backgroundCtx := context.Background()
160120

161-
if err := p2p.ServiceDiscoverer(fedCtx, node, token, p2p.NetworkID(r.Peer2PeerNetworkID, p2p.FederatedID), nil, false); err != nil {
162-
return err
163-
}
121+
if err := cli_api.StartP2PStack(backgroundCtx, r.Address, token, r.Peer2PeerNetworkID, r.Federated); err != nil {
122+
return err
164123
}
165124

166125
idleWatchDog := r.EnableWatchdogIdle

0 commit comments

Comments
 (0)