Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hotfix main bittensor #108

Merged
merged 102 commits into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
102 commits
Select commit Hold shift + click to select a range
0955708
cursor support
Nov 19, 2024
ecc4f2c
cursor support
Nov 19, 2024
83670be
cursor support
Nov 19, 2024
b458a27
cursor support
Nov 19, 2024
8fe3bd7
cursor support
Nov 19, 2024
ddd0cb1
cursor support
Nov 20, 2024
9bb70f7
cursor support
Nov 20, 2024
356f518
cursor support
Nov 20, 2024
e78e523
cursor support
Nov 20, 2024
963e759
cursor support
Nov 20, 2024
b2d24cf
cursor support
Nov 20, 2024
9b63b71
cursor support
Nov 20, 2024
1e62b2b
cursor support
Nov 20, 2024
720b4ed
cursor support
Nov 23, 2024
b3d82e2
cursor support
Nov 23, 2024
d8d344f
cursor support
Nov 23, 2024
a33c497
cursor support
Nov 23, 2024
c49818a
cursor support
Nov 24, 2024
ac330b5
cursor support
Nov 24, 2024
3d1d311
cursor support
Nov 24, 2024
5878148
cursor support
Nov 24, 2024
12246cb
cursor support
Nov 24, 2024
ec448a5
cursor support
Nov 24, 2024
3114042
cursor support
Nov 25, 2024
3cf370b
cursor support
Nov 25, 2024
ef3e925
cursor support add no stream
Nov 25, 2024
07dd27f
cursor support
Nov 25, 2024
7ec1424
cursor support
Nov 25, 2024
e9563a6
cursor support
Nov 25, 2024
bd8d5e7
cursor support
Nov 25, 2024
5f18b3c
cursor support
Nov 25, 2024
8ffb114
cursor support
Nov 25, 2024
8cb8426
cursor support
Nov 25, 2024
e0014c7
cursor support
Nov 25, 2024
9ae0ea0
cursor support
Nov 25, 2024
3508e7c
cursor support
Nov 25, 2024
50bad66
cursor support
Nov 25, 2024
29c4a51
cursor support test
Nov 25, 2024
dc8a1b1
cursor support test
Nov 25, 2024
53cdea7
cursor support
Nov 25, 2024
844dba4
cursor support
Nov 25, 2024
6954b42
cursor support
Nov 25, 2024
e917855
cursor support
Nov 25, 2024
bcb2d96
cursor support
Nov 25, 2024
41904a5
cursor support
Nov 25, 2024
216de3e
cursor support
Nov 25, 2024
02f29f2
cursor support
Nov 25, 2024
3a34b1e
cursor support
Nov 25, 2024
86358db
cursor support
Nov 25, 2024
4f75947
cursor support
Nov 25, 2024
7d0b86a
cursor support
Nov 25, 2024
67af7d7
cursor support
Nov 25, 2024
a901799
cursor support
Nov 25, 2024
9b68cd7
cursor support
Nov 26, 2024
6ccc316
cursor support
Nov 26, 2024
552f0d6
cursor support
Nov 26, 2024
4e81c15
cursor support
Nov 26, 2024
a05f7ee
cursor support
Nov 26, 2024
0cdd66f
cursor support
Nov 26, 2024
adc071d
cursor support
Nov 26, 2024
4dd7d6d
cursor support
Nov 26, 2024
0720d30
cursor support
Nov 26, 2024
0e05eb2
cursor support
Nov 26, 2024
91ac71c
cursor support
Nov 27, 2024
4b5e4ab
cursor support
Nov 27, 2024
694f2c5
cursor support
Nov 27, 2024
c3f1173
cursor support
Nov 27, 2024
b0191d7
cursor support
Nov 27, 2024
9abc81a
cursor support: add custom middleware
Nov 28, 2024
13c84e1
cursor support
Nov 28, 2024
ad5d951
cursor support
Nov 28, 2024
dcd1740
cursor support
Nov 28, 2024
60b6c08
cursor support
Nov 28, 2024
4517d97
cursor support rewrite axon constructor
Nov 28, 2024
8e64dd1
cursor support
Nov 28, 2024
258857d
validators/core/axon.py
Nov 28, 2024
f4e6a20
cursor support
Nov 28, 2024
ba02da7
cursor support
Nov 28, 2024
53b7a3b
cursor support
Nov 28, 2024
8ba14d7
cursor support issue fix
Nov 28, 2024
111b479
cursor support allow all origin
Nov 28, 2024
a71e154
cursor support
Nov 28, 2024
29e4b99
cursor support cors orgin added
Nov 28, 2024
ffa2338
cursor support issue fixed
Nov 28, 2024
e2115c3
increase input token limit to 10k
Nov 28, 2024
064ca0d
Update readme.md
surcyf123 Nov 29, 2024
10a7f31
Update readme.md
surcyf123 Nov 29, 2024
ef38cec
Update readme.md
surcyf123 Nov 29, 2024
d6dd3ec
Update readme.md
surcyf123 Nov 29, 2024
ace0f30
upgrade-version
Dec 2, 2024
69ffa3e
upgrade version
Dec 2, 2024
0a68521
version upgrade
Dec 3, 2024
609d2a9
upgrade version
Dec 4, 2024
33ab9df
upgrade-version miner issue fixed
Dec 4, 2024
a95fc3a
version upgrade
Dec 6, 2024
eded8de
upgrade version
Dec 8, 2024
cb894f9
Revert "Update readme.md"
Dec 8, 2024
40cd30d
fix some miner issue in cursor support
Dec 9, 2024
7f52a11
add more logging for cursor support
Dec 9, 2024
b36b18a
revert version to old in requirements.txt
Dec 9, 2024
9b34c46
axon revert changes
Dec 9, 2024
6b81033
dendrite issue fix
Dec 9, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,14 @@ pm2 start start_validator.py --interpreter python3 -- --wallet_name "default" --
```
---

# Cursor App Setup
add env varialbe CURSOR_API_KEY to .env file
go to inside of cursor directory and run this command.
```bash
pm2 start start_cursor.sh --name cursor_app
```
for settings in cursor. Pls check this [Cursor README](./cursor/readme.md)

## License
This repository is licensed under the MIT License.
```text
Expand Down
2 changes: 1 addition & 1 deletion cortext/protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ class StreamPrompting(bt.StreamingSynapse):
default={},
title="miner_info",
)
time_taken: int = pydantic.Field(
time_taken: float = pydantic.Field(
default=0,
title="time_taken",
)
Expand Down
18 changes: 0 additions & 18 deletions cursor/Dockerfile

This file was deleted.

29 changes: 29 additions & 0 deletions cursor/app/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
llm_models = [
{
"id": "gpt-4o",
"name": "Meta: gpt-4o Instruct",
"created": 8192,
"description": "OpenAI gpt-4o model.",
"context_length": 8192,
"architecture": {"modality": "text->text", "tokenizer": "gpt-4o", "instruct_type": "gpt-4o"},
"pricing": {"prompt": "0.000000001", "completion": "0.000000001", "image": "0", "request": "0"},
},
{
"id": "chat-claude-3-5-sonnet-20240620",
"name": "Meta: claude-3-5-sonnet-20240620 Instruct",
"created": 8192,
"description": "claude-3-5-sonnet-20240620.",
"context_length": 8192,
"architecture": {"modality": "text->text", "tokenizer": "claude-3-5-sonnet-20240620", "instruct_type": "claude-3-5-sonnet-20240620"},
"pricing": {"prompt": "0.000000001", "completion": "0.000000001", "image": "0", "request": "0"},
},
{
"id": "chat-llama-3.1-70b-versatile",
"name": "Meta: llama-3.1-70b-versatile Instruct",
"created": 8192,
"description": "llama-3.1-70b-versatile.",
"context_length": 8192,
"architecture": {"modality": "text->text", "tokenizer": "llama-3.1-70b-versatile", "instruct_type": "llama-3.1-70b-versatile"},
"pricing": {"prompt": "0.00000001", "completion": "0.000000001", "image": "0", "request": "0"},
}
]
28 changes: 28 additions & 0 deletions cursor/app/core/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import dataclasses
from dataclasses import dataclass
from dotenv import load_dotenv
import os

# Load environment variables from .env file
load_dotenv()


@dataclass
class Config:
wallet_name: str
wallet_hotkey: str
api_key: str

@staticmethod
def from_env() -> "Config":
"""Load configuration from environment variables."""
return Config(
wallet_name=os.getenv("WALLET_NAME", "default"), # Default to an empty string if not set
wallet_hotkey=os.getenv("HOT_KEY", "default"),
api_key=os.getenv("CURSOR_API_KEY", "")
)


# Load config
config = Config.from_env()

102 changes: 102 additions & 0 deletions cursor/app/core/dendrite.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import asyncio
from typing import Union, AsyncGenerator, Any

import aiohttp
import bittensor as bt
from aiohttp import ServerTimeoutError, ClientConnectorError, ClientConnectionError
from bittensor import dendrite
import traceback
import time
from typing import Optional, List

from .protocol import StreamPrompting


class CortexDendrite(dendrite):
task_id = 0
miner_to_session = {}

def __init__(
self, wallet: Optional[Union[bt.wallet, bt.Keypair]] = None
):
super().__init__(wallet)

async def call_stream(
self,
target_axon: Union[bt.AxonInfo, bt.axon],
synapse: bt.StreamingSynapse = bt.Synapse(), # type: ignore
timeout: float = 12.0,
deserialize: bool = True,
organic: bool = True
) -> AsyncGenerator[Any, Any]:
start_time = time.time()
target_axon = (
target_axon.info()
if isinstance(target_axon, bt.axon)
else target_axon
)

# Build request endpoint from the synapse class
request_name = synapse.__class__.__name__
endpoint = (
f"0.0.0.0:{str(target_axon.port)}"
if target_axon.ip == str(self.external_ip)
else f"{target_axon.ip}:{str(target_axon.port)}"
)
url = f"http://{endpoint}/{request_name}"

# Preprocess synapse for making a request
synapse: StreamPrompting = self.preprocess_synapse_for_request(target_axon, synapse, timeout) # type: ignore
max_try = 0
timeout = aiohttp.ClientTimeout(total=100, connect=timeout, sock_connect=timeout, sock_read=timeout)
connector = aiohttp.TCPConnector(limit=200)
session = aiohttp.ClientSession(timeout=timeout, connector=connector)
try:
while max_try < 2:
async with session.post(
url,
headers=synapse.to_headers(),
json=synapse.dict(),
) as response:
# Use synapse subclass' process_streaming_response method to yield the response chunks
try:
async for chunk in synapse.process_streaming_response(response, organic): # type: ignore
yield chunk # Yield each chunk as it's processed
except aiohttp.client_exceptions.ClientPayloadError:
pass
except ConnectionRefusedError as err:
bt.logging.error(f"can not connect to miner for now. connection failed")
max_try += 1
continue
except ClientConnectorError as err:
bt.logging.error(f"can not connect to miner for now. retrying")
max_try += 1
continue
except ClientConnectionError as err:
bt.logging.error(f"can not connect to miner for now. retrying")
max_try += 1
continue
except ServerTimeoutError as err:
bt.logging.error(f"timeout error happens. max_try is {max_try}")
max_try += 1
continue
except Exception as err:
bt.logging.error(f"{err} issue from miner {synapse.uid} {synapse.provider} {synapse.model}")
finally:
pass
break

except Exception as e:
bt.logging.error(f"{e} {traceback.format_exc()}")
finally:
synapse.dendrite.process_time = str(time.time() - start_time)
await session.close()

async def call_stream_in_batch(
self,
target_axons: List[Union[bt.AxonInfo, bt.axon]],
synapses: List[bt.StreamingSynapse] = bt.Synapse(), # type: ignore
timeout: float = 12.0,
deserialize: bool = True,
) -> AsyncGenerator[Any, Any]:
pass
52 changes: 24 additions & 28 deletions cursor/app/core/middleware.py
Original file line number Diff line number Diff line change
@@ -1,33 +1,29 @@
import time
from fastapi import HTTPException
from fastapi import FastAPI, Depends, HTTPException, Request
from cursor.app.core.config import config
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.responses import JSONResponse
# Your predefined valid API keys
VALID_API_KEYS = {config.api_key}


async def verify_api_key_rate_limit(config, api_key):
# NOTE: abit dangerous but very useful
if not config.prod:
if api_key == "test":
return True
class APIKeyMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request: Request, call_next):
# Get the API key from the `Authorization` header
if request.method == "OPTIONS":
return await call_next(request)

rate_limit_key = f"rate_limit:{api_key}"
rate_limit = await config.redis_db.get(rate_limit_key)
if rate_limit is None:
async with await config.psql_db.connection() as connection:
# rate_limit = await get_api_key_rate_limit(connection, api_key)
if rate_limit is None:
raise HTTPException(status_code=403, detail="Invalid API key")
await config.redis_db.set(rate_limit_key, rate_limit, ex=30)
else:
rate_limit = int(rate_limit)
if not request.headers.get("Authorization"):
return JSONResponse(
{"detail": "Invalid or missing API Key"}, status_code=401
)

minute = time.time() // 60
current_rate_limit_key = f"current_rate_limit:{api_key}:{minute}"
current_rate_limit = await config.redis_db.get(current_rate_limit_key)
if current_rate_limit is None:
current_rate_limit = 0
await config.redis_db.expire(current_rate_limit_key, 60)
else:
current_rate_limit = int(current_rate_limit)
api_key = request.headers.get("Authorization").split(" ")[1]

await config.redis_db.incr(current_rate_limit_key)
if current_rate_limit >= rate_limit:
raise HTTPException(status_code=429, detail="Too many requests")
# Validate the API key
if not api_key or api_key not in VALID_API_KEYS:
return JSONResponse(
{"detail": "Invalid or missing API Key"}, status_code=401
)

# Proceed to the next middleware or route handler
return await call_next(request)
Loading
Loading